Archive for May, 2012

Andrew Rybak

Webinar Reminder

Thursday, May 31st, 2012

A reminder about our upcoming webinar on June 13th at 1pm EST. During this webinar NTG and Appcelerator will discuss mobile development strategies. We are particularly excited that Appcelerator’s Mike King will be joining us to share his thoughts and insight. Prior to joining Appcelerator, Mike was Research Director for Mobile at the Gartner Group. He has authored Gartner’s Magic Quadrants for MCAP (Mobile Consumer Application Platforms) and MEAP (Mobile Enterprise Application Platforms), as well as the Magic Quadrants for Wireless LAN, U.S. Wireless Carriers, and the Packaged Mobile Applications Market Scope.

This event promises to be highly informative. We invite you to join us; you can register at: https://ntg.adobeconnect.com/_a164689/mobile-dev-strategy/event/registration.html

Rod Nolan

Getting started with AIR and BB10

Wednesday, May 23rd, 2012

I just started to play with the latest BB10 SDK for Adobe AIR. I had a couple of issues right away so I’m going to document them here to save you the headache.

First, make sure you download the correct SDK. Sounds simple, I know, but it wasn’t immediately apparent that there are currently two different SDKs available for download.

  • BlackBerry PlayBook SDK for Adobe AIR, easy to find but not the one I wanted
  • BlackBerry 10 SDK for Adobe AIR beta, the one I wanted but tucked out of the way

The Tools link in the bottom half of the page points to Tablet OS SDK for Adobe AIR v2.0 which is not the right version. If you’re after the BB10 SDK, you have to click on the rotating banner above the Tools link when it comes around to the “BlackBerry 10 SDK for Adobe AIR beta now available” section. That will eventually bring you to the page where you can download the BlackBerry 10 SDK for Adobe AIR v3.0 beta. Here’s the page https://bdsc.webapps.blackberry.com/air/beta/download/sdk/ where you’ll also find the link to download the new simulator. Moral of the story: don’t ignore rotating banners.

After installing the SDK and the BB10 simulator, I tried to run the Hello World sample as described here https://bdsc.webapps.blackberry.com/air/beta/documentation/aa_getting_started_bb10/Create_your_first_application_FB_ms_2006005_11.html and I got some errors on the imports for classes from the qnx.dialog package.

I had checked this option: Project Properties > ActionScript Build Packaging > BlackBerry > Add platform specific libraries to the class path so I went on the hunt for qnx.dialog. This is what I found.

all four swcs are present...

... but there's no qnx.dialog package anywhere

I found two entries in the forums which led me to the solution but to summarize, here’s what you have to do in Flash Builder 4.6:

  • Project Properties > ActionScript Build Path > Add Folder > C:\Program Files (x86)\Research In Motion\blackberry-tablet-sdk-3.0.0\frameworks\libs\qnx\ane
  • Project Properties > ActionScript Build Packaging > BlackBerry > Native Extensions tab > turn on all the Package checkboxes (might have to scroll horizontally to see them)
This links in the additional extensions required to use all the APIs.

Read this for the background story: http://supportforums.blackberry.com/t5/Adobe-AIR-Development/BB10-Error-1065-SkinAssets-is-not-defined/td-p/1720721

You may have to rework some imports in the sample code to refer to the qnx classes instead of the flash classes but that should do it. It’s also worth noting that this doesn’t seem to be a problem with FDT, only Flash Builder.

Happy coding.

 

 

Andrew Rybak

4 Steps to Create a Mobile Development Strategy

Wednesday, May 23rd, 2012

Probably the single most common question I hear when talking to companies about their mobile projects is along the lines of:  How can I use a single code base to support Native, Hybrid and mobile web applications?

This is not at all surprising. Mobile apps can help organizations to better reach customers, or improve internal workflows, or reinforce their brand, or deliver a myriad of other benefits. But the costs associated with app development can quickly escalate, especially if you are targeting multiple platforms.  At NTG we have long helped companies evaluate their development options and select the right strategy. Sometimes we have advocated HTML5, other times it made more sense to develop multiple native apps, or to use a hybrid approach.  As the mobile market matured, we noticed an influx of MEAP/MCAP (Mobile Enterprise/Consumer Application Platform) providers offering yet another option for developing mobile apps.

After a thorough evaluation of the various players in the market, NTG reached out to Appcelerator and formed a partnership whereby we are qualified to provide Appcelerator related development and enablement services.

On Wed, July 13th, at 1pm EST we will be hosting a webinar to discuss how organizations can deploy Appcelerator and develop a sound mobile strategy. Please join us and Mike King, Principal Mobile Strategist for Appcelerator and formerly Gartner’s Research Director for Mobile, as we outline the 4 key steps for creating a successful, sustainable, mobile application strategy. You can register by clicking through to this link: https://ntg.adobeconnect.com/_a164689/mobile-dev-strategy/event/registration.html

It promises to be an informative discussion. I hope you can join us.

oliverm

BlackBerry Hackathons – Come out and Play(Book)!

Wednesday, May 16th, 2012

I’m currently in Bogotá, Colombia taking part in my third Hackathon on behalf of RIM. These hackathons are two-day events where local developers get the opportunity to interact directly with experts in PlayBook development. They also get a free PlayBook just for showing up!

We typically have a team of three experts covering AIR, HTML5/WebWorks and Native development. Most of the events have been focused on game development, but I’ve also done one centred around business apps using WebWorks.

Developers, either in teams or individually, work some long hours over the two day period. At the end of the second day, their apps are judged and winners awarded additional prizes. Nothing like a bit of competition to bring out the best in a dev team!

And with BB10 on the horizon, there’s a lot of anticipation from developers. Keep your eyes open for an event coming to your city this summer. Hope to see you there!

alaint

Android: Using the Soundpool Class and MediaPlayer for online streams

Thursday, May 10th, 2012

By Alain Thibodeau – Consultant

 

Android: Using the Soundpool Class

There are times when you want to play a short sound in your application warning the user that something has happened, or just to add sound effects. Using the MediaPlayer is a good way of playing a sound, but it is system taxing if you are using more than one sound, and playing them at the same time. The SoundPool class will allow you to manage and play multiple short sounds.

Below is a simple example of using the SoundPool class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package com.newyyz;

import android.app.Activity;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class SoundPoolActivity extends Activity {

SoundPool soundPool;
int ringSound = -1;
int bangSound = -1;

private Button btnPlayRing;
private Button btnPlayBang;
private Button btnPlayAll;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.main);

btnPlayRing = (Button) findViewById(R.id.btnRing);
btnPlayBang = (Button) findViewById(R.id.btnBang);
btnPlayAll = (Button) findViewById(R.id.btnAll);

setVolumeControlStream(AudioManager.STREAM_MUSIC);

soundPool = new SoundPool(2, AudioManager.STREAM_MUSIC, 0);
bangSound = soundPool.load(this, R.raw.hit, 1);
ringSound = soundPool.load(this, R.raw.ring, 1);

btnPlayRing.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
soundPool.play(ringSound, 1, 1, 0, 0, 1);
}
});

btnPlayBang.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
soundPool.play(bangSound, 1, 1, 0, 0, 1);
}
});

btnPlayAll.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
soundPool.play(bangSound, 1, 1, 0, 0, 1);
soundPool.play(ringSound, 1, 1, 0, 0, 1);
}
});
}
}

We start off on line 22 in the onCreate() method setting the content to our layout resource and preparing three buttons. These buttons will play our sound effects. The first one will play the ring sound, the second will play the bang sound and the third one will play both sounds at the same time.

Next we set the volume controls to the music stream on line 31. Then we create a soundpool and configure it to handle 2 concurrent streams. Set this value to what your needs are, usually around 15-20 if you are creating a game.

Once the soundPool is created,  we can load our sound files, the soundpool’s load method will return a handle so we can reference the sounds when we need them.

Finally, we have our listeners on each button that call the sounpool’s play method. The first argument is the sound’s handle that we received from the load method. The second and third arguments are the left and right volume that range between 0 and 1. The next one is the priority. Following the priority is the loop count with -1 for looping forever. The last argument is the playback rate, which increases or decreases the speed of the audio.

This is a brief example demonstrating the use of the soundPool class. For production, you would consider using a HashMap to keep track of your sounds, and have only one method to play them. Also, to be memory friendly, unloading sounds when no longer needed or releasing the soundPool altogether is a good idea.

soundPool.unload(ringSound);
or
soundPool.release();

 

Android: Using the MediaPlayer for Online Streams

We’ve looked at ways of making use of the SoundPool class for smaller sounds like sound effects in a previous post. But, what about streaming audio from a server? Like an online radio station. This can be easily done using the MediaPlayer class.

Below is a quick and simple example using the MediaPlayer for streaming online content.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package com.newyyz;

import android.app.Activity;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class StreamingAudioPlayerActivity extends Activity {

private Button playButton;
private Button stopButton;
private EditText urlEditText;
private TextView statusText;
private MediaPlayer mediaPlayer;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.main);

initView();
initMediaPlayer();
}

private void initView() {
urlEditText = (EditText) findViewById(R.id.UrlEditText);
urlEditText.setText("http://playradio.podzone.org:9090/Play96.mp3");

statusText = (TextView) findViewById(R.id.status);

playButton = (Button) findViewById(R.id.playButton);
playButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
playStream();
}
});

stopButton = (Button) findViewById(R.id.stopButton);
stopButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
stopStream();
}
});
}

private void initMediaPlayer() {
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mediaPlayer.start();
statusText.setText("Playing...");
}
});
}

private void playStream() {
statusText.setText("Loading...");
playButton.setVisibility(View.GONE);
stopButton.setVisibility(View.VISIBLE);

try {
mediaPlayer.setDataSource(urlEditText.getText().toString());
mediaPlayer.prepareAsync();
} catch (Exception e) {
e.printStackTrace();
}
}

private void stopStream() {
playButton.setVisibility(View.VISIBLE);
stopButton.setVisibility(View.GONE);
statusText.setText("");
mediaPlayer.stop();
mediaPlayer.reset();
}

@Override
protected void onDestroy() {
super.onDestroy();
mediaPlayer.release();
}
}

As usual in our onCreate() method we setup the view. In this case we setup an EditText, TextView and two button controls. One button is for playing and the other is for stopping the stream. The EditText control is for our stream’s URL, and the TextView control is for giving the user some feedback about what is going on.

The next step is to create our MediaPlayer instance which we do in the initMediaPlayer() method. We also set the audio stream type and most importantly a listener for when the stream has finished preparing. In this example we are using the asynchronous version of the MediaPlayer’s prepare method. The reason we are preparing the MediaPlayer asynchronously is that we are accessing a stream on the Internet. Because of this, preparing may take some time. If we were to use the synchronous prepare method, it would lock the application until the player is ready.

Upon hitting play, we update the buttons and the status. At this point we are ready to set the datasource and prepare our MediaPlayer instance. Once the MediaPlayer is prepared, we play the stream in the OnPreparedListener();

Stopping the stream is done in the stopStream() method. We simply swap our buttons and stop the MediaPlayer. Resetting the MediaPlayer will put the player in its uninitialized state so we can set a new (or the same) data source and re-prepare.

Should the user exit the app, we will want to clean up. This is handled in the override of the onDestroy() method where we simply release the mediaPlayer. Based on what your needs are, you will handle the MediaPlayer for the various activity’s lifecycle phases.

So there we have it, a very simple media player for handling online streams. This could be the start of a very compelling Android application that can handle online streams, local files and video.