Monday, February 18, 2013

git for OS X

If you are a programmer, I can guarantee you, you will or should want to use some sort of version control system. Version control is incredibly important, when I first started coding I thought just having a few backups every now and then on a random one of my flashdrives was sufficient, and truth be told, at that stage it was. Nothing I was doing was too hectic, nothing was drastically changing so I was content with a backup regardless of whether or not it was effective.

But lately, in the last 6months or so, I have realised I need something better than just somewhere to plonk my code when I've reached a certain goal. I needed something that would give me control over my code and allow me to: a) have a backup at all times, b) allow me to see what code was added removed and when, to locate bugs, and c) so other people I work with have access to my code without throwing a flashdrive at me or waiting for an email I forgot to send for the thirteenth time.

So I decided I needed some sort of VCS (version control system). I began looking around and was a little disappointed, nothing was very straight forward, everyone used a different system and there were so many systems. The most common ones in my experience are Subversion or SVN, Mercurial or Hg, Perforce, Bazaar and of course git.

NOTE: Please remember these 'systems' are just software, most of them do not have a GUI of any sorts and are almost exclusively command line tools. That said, there are plenty of GUI's available for each but require a separate download. (This confused me for a while, so don't get confused)

I decided to use git, after seeing companies like Google, Microsoft, Linux...and of course, the deciding factor, Android all use git, I presumed it would be a good system.

So I downloaded the install for my mac and tried to install it, but it didn't work. It has taken me till now to realise why and fix it. If you install XCode from the Appstore, along with the command line tools, a version of git will be installed, however, it is rather old and as of yet I have no idea how or if these install can be updated.

Now I will take you through installing git, including editing your bash_profile file on your computer to allow the use of git from where ever. This is something lacking in almost every single tutorial on git which really annoyed me greatly, and so I shan't do that to any one. Here we go:

NOTE: I am working on OS X version 10.8.2 on my MBP 15"

First we need git:
1.You can download it from git-scm.com
2.Double click on the .dmg file: It should look something like this...


 (If this is the first time installing or trying to install git, you can skip steps 3 and 4)

3.Once its unpacked copy the unisntall.sh script to your desktop



4.Open up your terminal (Either default Terminal or iTerm 2) and type sh, then drag the uninstall script onto the terminal and hit enter - follow the instructions that come up:




This script will uninstall any previous git instances on your computer, except the one installed by xcode

5. Once git is completely uninstall, run the install package, the .pkg file.


6. Click 'Continue' and follow the instructions to install git

7. YAY! Give yourself a big hug and pat on the back, you have successfully installed git. Now we need to make it easily callable from the command line. i.e. we don't want to have to find and navigate to  the file every time we want to use it

8. In your terminal type 'git' (no inverted comma's) and hit enter. If you see a whole bunch of commands come up, great, you are done. If not, continue on. It means that git successfully linked to the directory, for me it didn't do this for some reason.

NOTE: If you can use git as is, the next part is unnecessary, however it's useful if you ever install any other tools that aren't mapped, specifically when you build from source.

9. Navigate to your user profile, if you just opened the terminal you are probably already there, if not type, 'cd ~/' (no inverted comma's) and hit enter, you should now be where you need to be.

10. Now type 'nano .bash_profile' (no inverted comma's) and again hit enter

11. You will see a possibly empty, possibly not screen that looks a little like this:


As the name suggests this is your bash profile - most of the commands you call in the terminal are bash commands, and this little file directs your terminal to all your different programs that are accessed by the command line.

12. Now we need to add the path to git, it should be located at 'usr/local/git/bin', if we direct the terminal there we should be able to run git form anywhere. Type 'export PATH=${PATH}:/usr/local/git/bin' (no inverted comma's) into the space provided:


13. Press ctrl+x to exit, y to save and enter to confirm. Close the terminal and open it again, type 'git --version' (no inverted comma's) and you should see this:


The version of your git installation should be displayed.

Now you just have to learn to use git ;-). which is where the fun starts.

I will be writing another post on using git at a later stage. So keep posted :-)If anything isn't clear or work the way  I have described it, please let me know so I can edit the post and help others who may have similar issues.

Wednesday, February 13, 2013

Beanshell Scripting in Android

I needed to add a new feature to one of my apps. The ability to send the app a scripted set of instructions to execute when needed.
So to start I decided to try and get the Scripting part to work first, I will be adding push notifications at a later stage using GCM, but for now I just wanted to see if it would be possible to actually run a script in Android.

I had no idea where to start so I asked a Android programming buddy of mine, Toby Kurien (I hope he doesn't mind me mentioning him), and he suggested I look at Beanshell. Basically its Java in scripting form. And it looked perfect for what I needed. The only issue is I could find virtually zero documentation on how to include this in an Android project, it works in Java projects, and so I just presumed, based on Android using Java and Toby's suggestion, that it would work.

I set out to get it to work.

First things first, we need the library.
For a whole bunch of getting started documentation, you can check out the website.

I just downloaded the entire package, but I should imagine using just the core and classgen packages would be sufficient.

Anyway, onto the code.

Firstly you need to import the Interpreter like any other class and instantiate the Interpreter Object.

NOTE: I am using this in a Service, however it will work in an Activity or any other component I think.

//Imports the Interpreter
import bsh.Interpreter;

public class SomeService extends Service{

//Instantiates the interpreter object
Interpreter interpreter = new Interpreter();
private final IBinder mBinder = new SomeBinder();

 @Override
    public IBinder onBind(Intent arg0) {
        return mBinder;
    }

 @Override onCreate(){

    }
}

So now we have the Interpreter object and have imported it.
Now we can start using it.

I am just putting this in the onCreate() method, but you can run this in a method or a Thread or however you wish. I have also used it in two different ways, one is to direct it to a file which contains the script and the other is using a reader which has read the script. I also send an instance of the Service to the Interpreter which allows me run methods and send my application data or instructions from the script, which I think is vital for me


import bsh.Interpreter;

public class SomeService extends Service{

Interpreter interpreter = new Interpreter();
private final IBinder mBinder = new SomeBinder();
SomeService serv;

 @Override
    public IBinder onBind(Intent arg0) {
        return mBinder;
    }

 @Override onCreate(){
    serv = this;
    // Creates a File object with the location of the script basic.bsh 
    // (bsh - beanshell script)
    File file = new File(Environment.getExternalStorageDirectory() + "/script",
    "basic.bsh");
            try {
                // Creates a Reader which has read the file
                Reader reader = new FileReader(file);
                // Sets the variable myapp in the script to Service instance
                i.set("myapp", serv);
                //eval() is used to either run a String as a script or the reader
                i.eval(reader);
                //source() is used to run a script from the path name
                i.source(file.getAbsolutePath());
            //EvalError is from the Beanshell Interpreter, and the other two are the standard IO operation exceptions
            } catch (EvalError evalError) {
                evalError.printStackTrace();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
    }
   public void hello(String myName){
   Log.i("TAG","My name is: "+myName);
   }
}

I included a hello() method, which I will use in this example to demonstrate how to call it form within the script.

I must also mention, you can call Android classes into the script, I haven't used it extensively...actually I just used android logging, however, it works flawlessly. I will include an example in the script just for demonstration purposes.

My script will look something like this:

import android.util.Log;
myapp.hello("Sean");
Log.e("TAG","Hello from Beanshell");

And that's that. I use TextWrangler to create the script and then just load it onto the sdcard in the folder 'script'. You can of course decide on however you wish to put the script there, I am certain you could even include the scripts in the Android project itself, but this is what I did.

It's very simple and very effective. If anyone needs any help, please comment and I will get back to you as soon as I can. My next post will probably be on how to use GCM.

Wednesday, February 6, 2013

Timer Class and Alarm Manager


My app was working well. Perhaps not perfectly, but pretty close such that I was very happy with how it was going. My app had a Timer running every second, with a whole bunch of integers iterating and keeping time sensitive tasks in check.

For instance, I need a GPS location for my app, and i need it fairly often. I basically try to get a GPS fix every 5 min with a 2 min 'timeout', i.e. every 5 min it will turn the GPS on, if it cannot find a fix in 2 min it will turn off. If it does find a fix, it will turn off.

So obviously here i need two different integers, one iterating for the 5min counter and the other for the 2min counter, i realise i could use one counter and just have boolean for the state of GPS, but this is not all the counters do (I promise, there is always method to my madness).

My Timer looked something like this:



public class SomeService extends Service
{
public int fiveMinCounter = 0,twoMinCounter = 0;


 @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

 @Override
    public void onCreate(){
    Intent startActIntent = new Intent(context,Splash.class);

    startActPending = PendingIntent.getActivity(context, 0,startActIntent, 0);
    Notification noti = new NotificationCompat.Builder(
          context).setContentTitle(getResources().getString(R.string.app_name))
          .setSmallIcon(R.drawable.icon).setContentIntent(startAct)
          .setWhen(System.currentTimeMillis())
          .setContentText("Touch to open UI").getNotification();
    this.startForeground(1,noti);
    Timer timer  = new Timer();
    timer.schedule(new mTimerTask(),1000,1000);
    }  

public class mTimerTask extends TimerTask{

  @Override
     public void run(){
     //Run some code here
     fiveMinCounter++;
     twoMinCounter++;
     }
  }

}

So this was working fine, doing what I needed it to. However at one stage I started to notice that the GPS would hang sometimes...it would not turn off at all. After some investigation, I realised that not only was the GPS staying on, and subsequently annihilating my phones battery, but the counters had stopped increasing.
The Timer had stopped. Dead.

It no longer ran through the code I had specified. It stopped while the GPS was on, a most unfortunate time to stop.

I did a bit of digging and discovered a few other people who had similar issues with the Timer class. For some reason after an unspecified amount of time, supposedly when the phone goes into deep sleep, the Timer will stop. Even when it is embedded in a Service such as the one above, which is also a foreground service and should not be stopped even by the System. It didn't happen very often, but the sad truth is, if it happens once its dangerous. Especially a bug like this which can stall the GPS in the on state. A battery can literally drain in about 3 to 4 hours with the GPS on permanently.

I need a solution. Something that can do a similar thing, but will not be killed by the System randomly.

I found the Alarm Manager Class, which I have used previously for a task which needed to execute every 24 hours or so.

I altered my code to look like this:

public class SomeService extends Service
{
public int fiveMinCounter = 0,twoMinCounter = 0;
public static Receiver receiver;
public static long second = (long) 1000;
 @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

 @Override
    public void onCreate(){
    Intent startActIntent = new Intent(context,Splash.class);

    startActPending = PendingIntent.getActivity(context, 0,startActIntent, 0);
    Notification noti = new NotificationCompat.Builder(
          context).setContentTitle(getResources().getString(R.string.app_name))
          .setSmallIcon(R.drawable.icon).setContentIntent(startAct)
          .setWhen(System.currentTimeMillis())
          .setContentText("Touch to open UI").getNotification();
  
    this.startForeground(1,noti);
    
    if (receiver == null) {
         receiver = new Receiver();
         registerReceiver(receiver, new IntentFilter("KEEP_CONNECTION_ALIVE"));
        }
    AlarmManager alarmManager = (AlarmManager) context
                    .getSystemService(ALARM_SERVICE);
    Intent intent = new Intent("KEEP_CONNECTION_ALIVE");
    PendingIntent pendingInt = PendingIntent.getBroadcast(this, 2, intent, 
                    PendingIntent.FLAG_UPDATE_CURRENT);
    alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis(),
                    second, pendingInt);
    }  

public class Receiver extends BroadcastReceiver{

  @Override
     public void onReceive(Context context, Intent intent){
     //Run some code here
     fiveMinCounter++;
     twoMinCounter++;
     }
   }

}
That seems to have fixed the issue. There is another issue where there is a delay in the first execution of the BroadcastReceiver, but it seems to try and catch up executing the number of times it missed.

It runs as well now, and from what I have read about using AlarmManager.RTC_WAKEUP it will wake the phone up to run the code even if it is in deep sleep. So far I have noticed no negative impact on the battery life using this method.

I think the difference lies in the fact that the Timer Class is just that, a class where as the AlarmManager is a System service, so perhaps it is able to stay alive when the Timer would normally be killed.

Hope this helps someone who might have a similar issue to me.

Edit: I am trying to get all the code to be formatted and highlighted correctly, I am new to doing this in a blog, so give me a little break ;-)