Showing posts with label mobile. Show all posts
Showing posts with label mobile. Show all posts

Tuesday, October 27, 2015

PhoneGap-Plugin-Push Version 1.4.0 Has Been Released

The latest release of the PushPlugin is now available on npm. This release is the long awaited release that is fully tested with iOS9. I was able to test on an iPhone 6+ running iOS 8.4.1, iPod Touch running iOS 9.0.2 and an iPad Air 2 running iOS 9.1.0. Please let me know if you run into any problems with this release.

On Android the switch over to using Gradle is now complete. The deprecated gcm.jar has been removed from the plugin and replaced with the Google Play Services GCM framework. Even better news is that PhoneGap Build now supports Gradle builds.

The big feature that people have been clamoring for is background or silent notifications. It is now possible for your 'notification' event handler to run when you app is in the background on iOS and Android (support for Windows coming soon).

1.4.0 (2015-10-27)

Full Changelog
Implemented enhancements:
  • Use Google's InstanceID API #188
Closed issues:
  • How to handle a re-installed app? #203
  • interactive push notifications? #266
  • Empty registrationId Android #265
  • Run callback when clicking of notification body #261
  • Android BUILD FAILED #251
  • Re-register #250
  • how to work in background ? #249
  • installing plugin #244
  • No Sound and vibration #242
  • Unable to build apk #241
  • still having problems with build. #239
  • Registering on iOS 9 #238
  • Custom sound repeated multiple times on Android #237
  • Android: status bar notification is not shown #236
  • Multiple Push Notifications - phonegap build #234
  • error: cannot find symbol String token = InstanceID.getInstance(getApplicationContext()).getToken(senderID, GCM); #231
  • Problem using "ledColor" and "VibrationPattern" #229
  • Notification event receive, but not notification showing on android #228
  • Events for registration not being fired #227
  • 'registration' event not firing on windows phone #224
  • Can i subscribe to a topic in using plugin? #219
  • GCMIntentService.java:472: error: cannot find symbol iconColor #217
  • Push Plugin registering on iOS 9 Devices but not showing Notification #216
  • Receiving a notification "outside app" while in it? #213
  • iOS push not working for device tokens when spaces removed #212
  • Error: Plugin PushPlugin failed to install. #210
  • Build error #205
  • Android push.on('registration', cb) fires correctly on device, but not in emulator. #204
  • 1.3.0 version not compatible with "crosswalk" by PGB #199
  • How to get data on didReceiveNotification Background Process #198
  • PushNotification is not defined in some devices #196
  • not getting notifications on the Android device #195
  • Installation Errors #186
  • IOS: on registration fired twice #185
  • Build failed with exit code 8 #184
  • iOS: Not able to schedule local notification after adding the plugin #183
  • How to show multiple notifications individually in android? #181
  • iOS init option type #180
  • Building for Android is a quest #179
  • How do i tell if the user open the app by tapping the notification? #176
  • IOS custom push sound when app is in background #175
  • Hi guys please post full working procedure, I'm not able to get registration id also. Please help #174
  • Has anyone tested this plugin on windows? #173

Tuesday, August 25, 2015

PhoneGap-Plugin-Push Version 1.2.0 Released!

The latest release of the PushPlugin is now available on npm. This release focuses on bringing a number of enhancements to Android notifications.

Fear not fans of other platforms as subsequent releases will have more features for your OS of choice. In fact release 1.3.0 will center around iOS9 support.

Picture Notifications

Embed a large picture in your notification. You let the plugin know you want to display a picture by setting the style of the push to picture and then giving it a picture property.

For example:
{
    title:"Big Picture", 
    message: "This is my big picture message", 
    style: "picture",
    picture: "http://36.media.tumblr.com/c066cc2238103856c9ac506faa6f3bc2/tumblr_nmstmqtuo81tssmyno1_1280.jpg",
    summaryText: "The internet is built on cat pictures"
}
Produces the cat picture on the right.

Inbox Notifications

Instead of stacking notifications in the tray you can now add multiple notifications to a single entry in the tray by setting the style to inbox. The first notification that arrives looks like normal but the subsequent ones will look like an inbox.

For example:
{
    title:"My Title", 
    message: "My first message", 
    style: "inbox",
    summaryText: "There are %n% notifications"
}
Followed by:
{
    title:"My Title", 
    message: "My second message", 
    style: "inbox",
    summaryText: "There are %n% notifications"
}
Produces the notification above.

Finally, my favourite new addition...

Action Buttons

Your notification can include action buttons. If you wish to include an icon along with the button name they must be placed in the res/drawable directory of your Android project. Then you can send the following JSON from GCM:
{
    title:"AUX Scrum", 
    message: "Scrum: Daily touchbase @ 10am Please be on time so we can cover everything on the agenda.", 
    actions: [
        { icon: "emailGuests", title: "EMAIL GUESTS", callback: "app.emailGuests"},
        { icon: "snooze", title: "SNOOZE", callback: "app.snooze"},
    ]
}
This will produce the following notification in your tray:


When the user clicks on one of the buttons it will execute the JavaScript code you specified as a callback for that button.

Check out the plugin's README for more details.

Full Change Log
1.2.0 (2015-08-25)

Implemented enhancements:
  • Implement Big Picture Style for Android #75
  • Implement Inbox style for Android #74
  • on("registration" is not getting called... #66
  • multi-line text support #63
  • Add image property to iOS and Android #39
  • Programmatically register #31
Fixed bugs:
  • Pushes being deleted from notification bar when cold start #67
  • No default sound in Android #53
  • Multiple push notification problem #48
Closed issues:
  • oficial push plugin and windows and wp8 compatibility #71
  • On Android, GCMIntentService.onError() doesn't get passed to the JavaScript "error" event #65
  • Android: add property to vibrate phone on received notification #61
  • push.on => "registration" will trigger twice times that only in iOS #57
  • Publish plugin to PhoneGap Build #22
Merged pull requests:

Wednesday, June 10, 2015

Video of PhoneGap Day EU 2015 - Push N' Pull Presentation

The video for my Push N' Pull presentation is now available.



If you want to get a copy of the slides please check out my previous post.

Tuesday, May 19, 2015

PhoneGap Day EU 2015 - Push N' Pull

Yesterday, I was happy to present at PhoneGap Day EU in Amsterdam. It's one of my favourite days of the year. Besides getting to hang out with all of my co-workers who I rarely get to see in person as we are separated by half a continent I get to talk in person with the people who use our software.

At PG Day I was presenting on the work that we've been doing in order to make the lives of developers easier. My presentation introduces the new and improved Push Plugin as well as the completely new Content Sync Plugin. I'll be blogging more about these two new plugins in the up coming weeks but for now if anyone wants to check out the slides they are embedded below:

Wednesday, April 3, 2013

My Home Screen

Kind of a departure from my regular posts but here is what my is currently on the home screen of my Nexus 4. Look it over and share with me what apps must be on your home screen.

Twitter - pretty obvious what this is used for. Today, hockey trade updates. Great new holo themed update released.

CIBC - my bank

theScore - out of all the mobile apps for quickly checking hockey scores (anyone see a pattern?) this one is my favourite. Apps like TSN and NHL GameCenter take too much time to load.

Untappd - one of my favourite apps built on top of the PhoneGap framework. It is a social beer check in app. Great to see what your friends are drinking and helps find new beers.

Gmail - All. The. Emails.

feedly - with the upcoming demise of Google Reader I've completely switched over to feedly for my RSS reading. It's a great app that syncs with Google Reader and has a great UI experience.

Google+ - I'm not completely sold on this app yet. I know Google wants it to be a Twitter/Facebook killer but until more of my friends start using it and the network effect takes over it won't be used as much as they'd hope.

Pocket Casts - after trying out a bunch of different podcast listening apps I've settled on Pocket Casts. It has a great UI and most importantly has variable rate playback which is a must for me. If I can't listen to podcasts at 2.0x speed I go crazy listening to the um's and ah's.

IMDB - I don't even think I can watch TV or Movies without this app. I'm constantly using it to look up what other shows/movies that actor was in.

TWN - The Weather Network, pretty useful app but it may be supplanted by the weather card in Google Now.

Starbucks - I'm a coffee addict. I use the Starbucks app to pay for my coffee fix whenever I can. Plus, it's one less card I have to carry around in my Costanza sized wallet.

OPL - Ottawa Public Library, I'm an avid reader who is constantly churning through books. Luckily Ottawa has a great public library system that feeds my addiction. Again, one less card is needed in my wallet.

Google Folder - this is my shortcut to all the other Google apps I use frequently but not enough to make the home screen like Play Music, YouTube, Calendar and People.

Instagram - currently testing out this photo service to see if it is a suitable replacement for the stock camera.

Instapaper - absolutely fantastic app for saving articles and reading them later, even when you are off line.

Play Store - with the new phone I find myself constantly installing new apps so the store has made it's way to the home screen.

So that's it. What are some of your favourite apps that I'm missing?

Saturday, February 9, 2013

PhoneGap Plugin Updates to TelephoneNumber, IMEI and TTS

I've updated the TelephoneNumber, IMEI and TTS plugins to use the Apache Cordova 2.2.0 API's. That means no more deprecation notices in the Java code and the JavaScript code uses the cordova.require method. However, I'm still slapping the objects into window.plugins so you shouldn't need to change any of your JavaScript code after upgrading.

This completes the upgrade of my plugins that everyone voted on. Next up will be some new work and hopefully I'll be able to get to that WebSpeech shim I've been threatening to do.

Monday, January 21, 2013

PhoneGap Plugin Updates

In the past few days I've spent some time upgrading my plugins so they work in PhoneGap/Cordova 2.2.0 or greater without requiring the users to make any changes. I've done the FtpClient and VideoPlayer. Basically I'm removing any deprecation warnings by moving from the org.apache.cordova.api.Plugin class to the org.apache.cordova.api.CordovaPlugin class. Also, I've been moving to the cordova.require way of defining a plugin on the JavaScript side while retaining the old window.plugins object for people who've written their code to use this object.

I'm currently running a poll to see which of my plugins should get upgraded next so go please vote for your favourite:


I'll start picking them off as I have time this week.

Monday, August 8, 2011

Our OSCON PhoneGap Slides

Well the PhoneGap presentation that Becky Gibson and I gave at OSCON this year seems to have been well received. Thirteen people have rated us so far giving us an average of 4.15 stars out of 5 which I consider to be pretty good. If you are looking for the slides and example code you can find it here.

Next up for me is an internal presentation at the end of the month and then I will head down to Ottawa chapter of CocoaHeads to talk about developing cross platform mobile apps with PhoneGap.

Update: Now available on SlideShare as well.

Saturday, July 30, 2011

Upgrading your PhoneGap Android Application to 1.0.0

With the release of PhoneGap 1.0.0 some folks may run into some problems upgrading their existing applications to the latest version.  If you are not using "droidgap create" to generate a brand new Eclipse project using PhoneGap 1.0.0 here are a few things you should be aware of:
  1. Obviously you'll need to modify the script tag that references phonegap-{ver}.js to be phonegap-1.0.0.js.
  2. Secondly you'll need to remove the current phonegap-{ver}.jar from the build path and add phonegap-1.0.0.jar to the build path. 
  3. If you run your app and it gets the Force Close dialog then you probably didn't copy plugins.xml into the res/xml directory in your application. If the xml directory doesn't exist create it!
  4. If you are unable to open a second html page in your app then you're missing the following tag which should be placed in the application tag of your apps AndroidManifest.xml:

    <activity android:name="com.phonegap.DroidGap" android:label="@string/app_name" android:configChanges="orientation|keyboardHidden">
    <intent-filter>
    </intent-filter>
    </activity>

    Please note after you add this activity you should have two activities under your applications tag. The above activity should not replace the one currently in your application tag.
  5. If you see and error about PluginManager.addService() not existing then you are using old style plugins. Go into the Plugins .js file and comment out of straight up delete the PluginManager.addService() line from the PhoneGap.addContructor() method.  Then you should add a plugin tag to the plugins tag in your plugins.xml.

    For instance if you are using the TTS plugin you'd add:

    <plugin name="TTS" value="com.phonegap.plugins.speech.TTS"/>
This may not be an exhaustive list of issues you may run into on an upgrade but it is all I can think of right now.  If you find something else comment on this post and I'll update it.

Thursday, June 23, 2011

FTP Plugin for PhoneGap Android

I did this FTP plugin awhile back but forgot to push it to the main phonegap-plugin's repository. I've pushed it over now and I'm putting together this quick blog post to explain how to use it.

The ftp client allows you to upload and download files from within your PhoneGap Android application. It provides basic get and put functionality.

1. To install the plugin, move www/ftpclient.js to your project's www folder and include a reference to it in your html file after phonegap.{ver}.js.

<script type="text/javascript" charset="utf-8" src="phonegap.js"></script>

<script type="text/javascript" charset="utf-8" src="ftpclient.js"></script>

2. Create a directory within your project called "src/com/phonegap/plugins/ftpclient" and copy "src/com/phonegap/plugins/ftpclient/FtpClient.java" into it.

3. Add the following activity to your AndroidManifest.xml file. It should be added inside the <application> tag.

<activity android:name="com.phonegap.DroidGap" android:label="@string/app_name">
<intent-filter>
</intent-filter>
</activity>

4. Copy "libs/commons-net-2.2.jar" into the libs directory within your project. You will also need to right click on this file in eclipse and add the jar to the build path.

Once installed properly, you should be able to upload files using the following syntax:

window.plugins.ftpclient.put("test.txt", "ftp://username:password@ftp.server.com/test.txt;type=i", win, fail);

and of course download files using:

window.plugins.ftpclient.get("test.txt", "ftp://username:password@ftp.server.com/test.txt;type=i", win, fail);

I'm not sure how many people really need FTP functionality but it was an interesting exercise none the less.

Wednesday, May 18, 2011

Using the Media Class in PhoneGap

I've seen a lot of posts recently on the PhoneGap Google Group so I wanted to put something together illustrating the use of the PhoneGap Media class. While putting this example together I noticed a few quirks of the Media class which I'll try in describe in more detail so that other folks don't run into the same problems. Also, this example has been tested on Android but it, for the most part, should work on iOS as well. Part of PhoneGap 0.9.6 will be normalizing how the Media class works between all the major platforms so look for improvements soon.

The example will be a basic Media player with play/pause and stop functionality.  Here's a quick screen shot:


On Android you can create a Media object using one of three ways.  The first way is referencing a file in your "android_asset" directory.  For instance if you have a file called "test.mp3" in your projects "assets/www" directory you would create a new media object by doing:
myMedia = new Media("/android_asset/www/test.mp3");
The second way to create a media object is by referencing a file on your devices file system. Say for instance, you have a file at "/sdcard/test.mp3" of your device you would create the media object by doing:
myMedia = new Media("test.mp3");
You'll notice the "/sdcard/" portion of the file name is omitted. This is because on Android the Media object makes an assumption that the file is stored on your "/sdcard". Note: I may change this behaviour in an upcoming version of PhoneGap but I'll strive to retain backward compatibility.

The third and final way to create a media object is by URL:
myMedia = new Media("http://audio.ibeat.org/content/p1rj1s/p1rj1s_-_rockGuitar.mp3");
Now that we've got our media object we want to be able to do the sensible thing and be able to play the audio. For that we'll create a play button:
<a href="#" onclick="playAudio()"><img id="play" src="images/play.png" /></a>
and corresponding function:
function playAudio() {
  myMedia.play();
}
Now the stop button is just as simple:
<a href="#" onclick="stopAudio()"><img id="stop" src="images/stop.png" /></a>
function stopAudio() {
  myMedia.stop();
}
However, that's pretty lame as it would be great to be able to pause the audio playback so let's enhance out play and stop functions:
function playAudio() {
  if (!playing) {
    myMedia.play(); 
    document.getElementById('play').src = "images/pause.png";
    playing = true; 
  } else {
    myMedia.pause();
    document.getElementById('play').src = "images/play.png";    
    playing = false; 
  }
}

function stopAudio() {
  myMedia.stop();
  playing = false;
  document.getElementById('play').src = "images/play.png";    
}
Now when the user is playing some audio the play button image is changed to a pause button and hitting the pause button again will, well, pause the playing of the audio. I'm cheating a little bit by using a global variable called playing as it could easily be changed to check what the currently set image is and doing the correct action.

Of course it is always nice to know where we are at in a given audio clip so we can add some functionality to get the current position of where we are at in the file. So let's create a function that will run every second and update our HTML with the current position of the audio file.
<p id="audio_position">0.000 sec</p>

var mediaTimer = setInterval(function() {
  myMedia.getCurrentPosition(
    function(position) {
      if (position > -1) {
        document.getElementById('audio_position').innerHTML = (position/1000) + " sec";
      }
    },
    function(e) {
      console.log("Error getting pos=" + e);
    }
    );
}, 1000);

That's all well and good but there is one thing that's slipped by our notice so far. When an audio clip finishes playing the pause button should become a play button in case the user wants to play the clip again. That can be accomplished by adding a success call back to our Media object constructor. The success call back is executed when the clip has finished playing. So we'll now instantiate our media like this:
myMedia = new Media("/android_asset/www/test.mp3", stopAudio);
So what we have here are the beginnings of a audio player application for Android. In part two of this article I'll enhance the app with the File System and Directory API showing you how to scan your device for audio files.

The HTML and images can be found here and below is a listing of the HTML code uses in this article. I added a select box so that users could switch between the different ways of creating a Media object. You'll have to supply your own MP3 file as I don't want the RIAA coming after me.

Monday, May 9, 2011

Text to Speech Plugin for PhoneGap Android

On Saturday I participated in the Droidhack put on by Ottawa Android downtown at the Code Factory. The Droidhack is an opportunity for Android developers to get together to work on open source Android projects. Luckily, my day job is working on an open source Android project but the Droidhack gave me the opportunity to work on a plugin that I've wanted to do for awhile, text to speech.

At a former job I developed telephony applications that took advantage of speech recognition and text to speech. Since android has built in text to speech functionality I figured I would expose the functionality to PhoneGap developers via a plugin. Maybe some other folks can take advantage of this plugin and provide more accessible Android applications.

In order to use the TTS plugin wait until you get the deviceready event and then call:
window.plugins.tts.startup(startupWin, fail);
This will start the TTS service on your device. However, the service will take a bit of time to start so the startup success callback is first called with a value of TTS.INITIALIZING which tells you that the service is initializing. Once the service is completely started the success callback is executed again with a value of TTS.STARTED which means we are ready to synthesize text.
function startupWin(result) {
 // When result is equal to STARTED we are ready to play
 if (result == TTS.STARTED) {
  //Ready to go
 }
}
To have your device play some text you simply call the speak method:
window.plugins.tts.speak("The text to speech service is ready");
If you want to have some silence between utterances you can call the silence method:
window.plugins.tts.speak("Let me think.");
window.plugins.tts.silence(2000);
window.plugins.tts.speak("I do not know");
In the above example the TTS service will pause for 2 seconds between the two speak calls. Both the speak and silence methods allow you to provide optional success and error callbacks if you need that kind of information.

Of course all of the above examples assume you are using the English (American) package to speak your utterances. If want to find out what the currently assigned TTS language is you call the getLanguage method:
window.plugins.tts.getLanguage(win, fail);
The success callback has one parameter and that will be a text representation of the Locale currently set for the TTS service.

Now, Android by default supports the following languages for the TTS service English (American), English (UK), French, German, Italian and Spanish. However, it is not guaranteed that each package will be installed on your device. So before you set the TTS language you will want to check to see if it is available by calling the isLanguageAvailable method and in the success callback then you set the TTS language you want to use by executing the setLanguage method:
window.plugins.tts.isLanguageAvailable("fr", function() {
   window.plugins.tts.setLanguage("fr");
   }, fail);
And of course if you no longer need the TTS service than call the shutdown method to free up the resources:
window.plugins.tts.shutdown(win, fail);
If you don't call shutdown on the TTS service the service will be shutdown when your device exits.

The plugin is available at the Android PhoneGap Plugin repository. Please give it a download, try it out and let me know what you think.

The following listing shows a full example of using the TTS Plugin:

Wednesday, May 4, 2011

Overriding the Back Button in PhoneGap Android

Frequently PhoneGap applications consist of multiple screens represented by divs. Since Android users are conditioned to push the back button to return to the previous screen this causes some confusion as the default behaviour is to close the app. Luckily PhoneGap provides developers a way to over ride the default back button behaviour so they may provide their own back behaviour.

In release 0.9.4 the developer would have to wait for the deviceready event and call:

navigator.device.overrideBackButton();
document.addEventListener("backKeyDown", backPressed, false);

In order to setup and event handler for the back key and:

navigator.device.resetBackButton();

to revert to the default behaviour.

As of PhoneGap 0.9.5 we've made overriding the back button behaviour easier. You still have to wait for the deviceready event but the calls have been simplified to:

document.addEventListener("backbutton", onBackKey, false);

to register your event handler for the back key and:

document.removeEventListener("backbutton", onBackKey, false);

to revert to the default Android back button behaviour.

The following listing shows a full, yet contrived, example:

Friday, April 29, 2011

PhoneGap Lifecycle Events

With the release of PhoneGap version 0.9.5 all of the major platforms (Android, BlackBerry and iOS) now support lifecycle events. Documentation for the events will be available in the Events section of docs.phonegap.com but I thought I'd put together a small post explaining it in more details.

Whenever talking about events a finite state diagram is usually the best place to start.


When you start an application the load event is fired when all of the content has finished loading.  You can register an event listener for the load event in the body tag.
<script type="text/javascript" charset="utf-8">

function onLoad() {
  // handle on load event
}
</script>

<body onload="onLoad()">

However, this is not the most important event from a PhoneGap perspective. The PhoneGap API is not ready until you receive the deviceready event.  You should register for the deviceready event in your load event handler.  Wait until you get this event before you start calling PhoneGap API commands.
<script type="text/javascript" charset="utf-8">

function onLoad() {
  document.addEventListener("deviceready", onDeviceReady, false);
}

function onDeviceReady() {
  // PhoneGap is ready to be used
}
</script>

<body onload="onLoad()">

Once your application is up and running you can register for a couple of other lifecycle events in pause and resume.  The pause event is called when your application leaves the foreground and is suspended by the operating system.  The application is not closed it is just in the Paused state.  When the application is returned from the background and placed into the foreground the resume event is fired and your app is back in the Running state.
<script type="text/javascript" charset="utf-8">

function onLoad() {
  document.addEventListener("deviceready", onDeviceReady, false);
}

function onDeviceReady() {
  // Register the event listener
  document.addEventListener("pause", onPause, false);
  document.addEventListener("resume", onResume, false);
}

function onPause() {
  console.log("I've been paused");
}

function onResume() {
  console.log("I've been resumed");
}

</script>

<body onload="onLoad()">

When you application exits the unload event is called.  This is a useful event if your application needs to save some state data. You would register your unload listener the same as you would for the load event by adding it to the body tag.
<body onload="onLoad()" onunload="onUnLoaded()">

It is worth noting that if your application is in the Running state when it told by the OS to unload it will first be paused so the pause event will fire before the unload event.

If you want the full HTML listing you can find it here.