Monday 9 March 2015

A Great Breakdown of Angular

If you are having troubles with AngularJS and understanding scope, directives, and services; this guy does a great job of explaining everything. The video is a bit long, so make sure you have the time to watch the whole thing.

Saturday 7 March 2015

AirDroid

You've hopefully got a packaged app for your Android device by now. There are a few different ways of moving that your phone, but a handy app I found to help with that is called AirDroid. Instead of getting drivers for your phone and connecting via USB or downloading it from online storage, you can drop it to the AirDroid window and send the file straight to your phone. After that it's as simple as opening your notifications window and tapping on your app.

Now there's one thing to be aware of, your app will be unsigned. Which means your phone will complain about security issues, but you can bypass that warning and install it anyways. Just be careful if you use this method to install other unsigned apps. If it's code you don't trust, you probably shouldn't install it on your phone. But if you are testing your own app there should be nothing to worry about, security wise at least.

To find the .apk file after building it with cordova, navigate to your apps folder. From there it should be around here:

 \sidemenu\platforms\android\ant-buildCordovaApp-debug.apk

So once it's on our phone, run it like any other app.

Friday 6 March 2015

Setting up the Android Platform

I'm going to preface this is a warning. A lot can, and likely will go wrong when you attempt to package your app for each platform. I'll be covering android again, and most of the work is done via installing the various SDK's and ensuring the PATH environment variable is correct. If you haven't already, download and install the latest JavaSDK, Android, and Apache Ant. Java and Ant should automatically update your system's environment variables, but in the event it fails; you will be doing it yourself. Android should as well but it failed to in my case. Chances are though, you will need to add an Environment Variable yourself. So heres how to do it:

Windows 8:

  1.  Go to your windows start screen 
  2.  Type system into the search box and open it 
  3.  Open the Advanced System Settings on the left side of the window 
  4.  The button to access the Environment Variables should be right above the Cancel button in this window 
  5. Your variables should be in the bottom half of the window, that's where the system wide variables are. 

Environment Variables in this case is sort of a shortcut that the operating system knows of. When you run ipconfig from the command prompt, your computer knows exactly where to find it, regardless of your current working directory (which is usually in your documents folder). In the case where you are trying to run non-windows programs in that manner, you need to tell it where the relevant folders are. That's exactly what were doing with Environment Variables, we are creating shortcuts for the Git bash to use. So if you try to run a command in Git bash, and get an error about ANDROID_HOME, you know your Environment Variable for the Android SDK is not correct, or missing.

There should System variables for ADT_HOME, ANDROID_HOME, ANT_HOME,GIT_HOME, and JAVA_HOME. Additionally, there should a few in the PATH variable. The PATH variable is a pain. The window it is housed in cannot be resized, and you have a massive string contained in a small text window. For example, here's what my PATH variable looks like:

C:\ProgramData\Oracle\Java\javapath;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Windows Kits\8.1\Windows Performance Toolkit\;C:\Program Files\Microsoft SQL Server\110\Tools\Binn\;C:\Program Files (x86)\Microsoft SQL Server\100\Tools\Binn\;C:\Program Files\Microsoft SQL Server\100\Tools\Binn\;C:\Program Files\Microsoft SQL Server\100\DTS\Binn\;C:\Program Files (x86)\Microsoft SDKs\TypeScript\1.0\;C:\Program Files\Microsoft SQL Server\120\Tools\Binn\;C:\Program Files\nodejs\;C:\apache-ant-1.9.3\bin;C:\Program Files (x86)\Git\cmd;C:\Program Files\Java\jdk1.8.0_25\bin;    %ADT_HOME%\tools;%ADT_HOME%\platform-tools\tools; %ADT_HOME%\tools;%ADT_HOME%\platform-tools\platform-tools\tools;    %ADT_HOME%\tools;;%GIT_HOME%\cmd;

It's ridiculous. So if you need to edit your PATH; I strongly suggest you copy the whole string into a document and edit it from there. Copy and paste it back into the tiny text box, and apply. But save your original PATH in case you mess something up.

The next thing to do is download Android API-19 using the android SDK manager, you may need to run it as an administrator.

If all of that works, you should be able to open Git bash and run these two commands

cordova platform add android

cordova build

If it throws an error, it should give some indication as to where your problem is. Likely an Environment Variable is pointed to the wrong folder, or something isn't installed. For example if it mentions Android-20, you need to download Android API-20.

Monday 2 March 2015

State Parameters and More Scope

In my last post I explained $scope a bit, in this post we expand on that and start manipulating scope along side the $stateParams. State Parameters are initially defined in the app.js file, right now we are interested in one in particular.

  .state('app.single', {
    url: "/playlists/:playlistId",
    views: {
      'menuContent': {
        templateUrl: "templates/playlist.html",
        controller: 'PlaylistCtrl'
      }
    }
  });


If you look at the url, you will notice something odd about the playlistId. A colon (the punctuation mark, kind of colon) precedes it, what is basically going to happen is; the last bit of the url will be assigned to a variable called playlistId.

Remember this line?
<ion-item ng-repeat="playlist in playlists" href="#/app/playlists/{{playlist.id}}">
Notice anything about the href? {{playlist.id}} is pulled from scope and used to create the url for that specific playlist. Then you can use $stateParams to include that id as a dependency, which then can be assigned to the $scope. How you take advantage of this is up to you, but I'm going to do something simple for demonstrative purposes. We are going to create an array of playlists and shift the id numbers of the Playlists so they are array friendly (start at zero).

The easier part is shifting id numbers, in app.js we are going to do this:

.controller('PlaylistsCtrl', function($scope) {
  $scope.playlists = [
    { title: 'Reggae', id: 0 },
    { title: 'Chill', id: 1 },
    { title: 'Dubstep', id: 2 },
    { title: 'Indie', id: 3 },
    { title: 'Rap', id: 4 },
    { title: 'Cowbell', id: 5 }
  ];
})
If my reasoning doesn't make sense now, it will later, hopefully. First, we need to create some playlists. Of course, whoever created this template doesn't know good music so I'm going to just copy paste fake song names... except for the cowbell playlist, I've got that covered.

So let's populate the playlist controller with actual playlists.

.controller('PlaylistCtrl', function($scope, $stateParams) {
  $scope.playlistSet = [
    [
      { track: '1', artist: 'Whoever'},
      { track: '2', artist: 'Whatever'},
      { track: '3', artist: 'Whenever'},
      { track: '4', artist: 'Whomever'}
    ],
    [
      { track: '1', artist: 'Whoever'},
      { track: '2', artist: 'Whatever'},
      { track: '3', artist: 'Whenever'},
      { track: '4', artist: 'Whomever'}
    ],
    [
      { track: '1', artist: 'Whoever'},
      { track: '2', artist: 'Whatever'},
      { track: '3', artist: 'Whenever'},
      { track: '4', artist: 'Whomever'}
    ],
    [
      { track: '1', artist: 'Whoever'},
      { track: '2', artist: 'Whatever'},
      { track: '3', artist: 'Whenever'},
      { track: '4', artist: 'Whomever'}
    ],
    [
      { track: '1', artist: 'Whoever'},
      { track: '2', artist: 'Whatever'},
      { track: '3', artist: 'Whenever'},
      { track: '4', artist: 'Whomever'}
    ],
    [
      { track: 'Honky Tonk Women', artist: 'The Rolling Stones'},
      { track: 'Were an American Band', artist: 'Grand Funk Railroad'},
      { track: 'Dont Fear the Reaper', artist: 'Blue Oyster Cult'},
      { track: 'Hair of the Dog', artist: 'Nazareth'},
    ]
  ];
  $scope.id = $stateParams.playlistId;
});
$scope.playlistSet is made up of an array, of arrays, of objects. And you will also notice how we used the playlistId to create $scope.id. We need that id to pick the right array to list in the playlist window.

The next part is to display all of that information using a small bit of HTML:
<ion-view view-title="Playlist">
  <ion-content>
    <ion-list ng-repeat="playlist in playlistSet[id]">
<ion-item>Track: {{playlist.track}} <br/> By: {{playlist.artist}}</ion-item>
</ion-list>
  </ion-content>
</ion-view>
That's what our playlist.html file looks like. What's happening is ng-repeat looks at each item in the array located at playlistSet[id]. The id chooses the appropriate set of songs, and then goes through the array of songs and lists the track and artist.

Here's a little walk through to help out, in case something didn't quite make sense.
 


You can get the app from my screencast here.