Sunday, 27 July 2014

How to edit What's New in Android application listing in Google Play Developer Console

From the All Applications list, select the application you want to add or modify the What's New section in Google Play Store application listing. This will open the Store Listing page for the app.  

Select APK at the left panel to open the APK page of the app. 

Click on the current published version with a status "in Prod", in the screenshot above it will be version 8 (2.3) which will open the APK Details window.

Scroll down to the bottom you will see the "What's new in this version?" and click on the section to Edit.

Finally click "Save and Publish" and it is done.

Monday, 29 July 2013

Freescale Cup 2013 Malaysia Hosted in Multimedia University

A total of 35 teams from 21 universities from all over Malaysia were competing in Freescale Cup 2013, hosted in Dewan Tun Canselor, Multimedia University on 20 July 2013 (Saturday). The Freescale Cup is a competition of a team of University students to build a model car that will race for speed around an unknown track with various obstacles. This year, participants have to program a FRDM-KL25Z: Freescale Freedom Development Board with Freescale Cup Shield to interface with camera and motors to intelligently follow a black line on the track.

Students from Multimedia University Cybertron Club have volunteered to help the organizer laying out the racing tracks. They were also helping in the preparations the day before the event.

MMU Vice President of Academic Prof. Dr. Ong Duu Sheng received a token of appreciation giving to MMU for sponsoring the venue for the event. From the comments of the organizer and participants from other universities, it is a great venue and gives a very pleasing experience.

Swinburne University won the first place with a cash prize of RM5000 with their outstanding car speed. They will join the Global Freescale Cup challenge held at Harbin, China, August 22-24 this year. University Malaysia Sabah and Monash University won the second (RM3000) and third place (RM1500) respectively.

MMU Cyber 1 from Multimedia University (Ms. Shameeny Raj A/P Siva Raj, Ms. Asuvani A/P D. Vasudhevan, Ms. Stephanie A/P Anthony Louis) has won the Best Design Award, a cash prize of RM500 with their unique Batman-inspired design. Spectators especially young kids were seems excited whenever this car was racing in the track.

All three MMU teams, MMU Cyber 1, MMU Cyber 2 (Mr. Yap Hon Shin, Mr. Heng Jia Wei, Mr. Ling Eng Han) and MMU Cyber 3 (Mr. Morteza Ozlati Moghadam, Mr. Mohamad Mahdi Saemi, Mr. Nima Shokohfar) under the advisory of Mr. Yap Wen Jiun and Mr. Lo Yew Chiong from Faculty of Engineering successfully completed the preliminary round to qualify for the final round joining the other 19 teams. All MMU teams then proceed to complete the more challenging final round and the fastest car among them, MMU Cyber 3 did give a good challenge to the top three teams with a just a few seconds slower.


Thursday, 15 November 2012

GDG DevFest KL 2012 Code Lab - Android + App Engine + GCM

This is the step-by-step guide to the Code Lab for GDG DevFest KL 2012 to build a simpler version of the Android application "Info Trafik" with an App Engine server.

1. Requirements:
  • A Google account to access Google API Console.
  • Eclipse
  • Google Plugin for Eclipse (Google App Engine SDK, Android ADT)
  • Android SDK (requires Android SDK Tools, Android SDK Platform-tools, SDK Platform (API 16), Android Support Library, Google Cloud Messaging for Android Library)

Setup Google API Access
2. Open Google API Console
3. If you haven't created an API project yet, click the "Create Project …"
If you have created API projects before, choose Other projects > Create
4. Enter a name and click Create Project
5. Copy down the SENDER_ID from the url (e.g. where XXXXXXXXXXXX is the SENDER_ID)
6. On the Services page, enable "Google Cloud Messaging for Android"
7. On the API Access page, select "Create new Server key..." and proceed with Create
8. Under the Key for server apps, copy down the API key

Setup Google App Engine
9. Open Google App Engine Adminstration Console 
10. Select "Create Application". For 1st time user, you need to verify the account by receiving a text message
11. Enter an Application Identifier & Application Title and select "Create"

Build Google App Engine Application
12. Start Eclipse and sign in with your Google Account (bottom right corner)
13. Select New Web Application Project
14. Enter the Project name "Codelab" & Package "my.devfestkl.codelab", untick Use Google Web Toolkit and click Finish
15. Open in src/my.devfestkl.codelab
16. Add these imports
resp.getWriter().println("Hello, world");
String last_id = "0";
// retrieve the Twitter search last ID 

URL url = new URL("" + last_id);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()), 8);
StringBuilder builder = new StringBuilder();
String line = "";
while ((line = reader.readLine()) != null) {
try {
    JSONObject jObject = new JSONObject(builder.toString());
    JSONArray jResults = jObject.getJSONArray("results");
    if (jResults.length() != 0) {
     // retrieve all GCM registration ID
      for (int i = 0; i < jResults.length(); i++) {
      JSONObject jResult = jResults.getJSONObject(i);
      // save the new Twitter search last ID
      resp.getWriter().append(jResult.getString("text") + "\r\n");
            // send the GCM message
    } else {
     resp.getWriter().append("No new tweet\r\n");
} catch (JSONException e) {
(Optional) change the LLMInfotrafik to another Twitter user
17. Select Deploy to App Engine
18. Click on App Engine project settings...
19. Enter the Application Identifier from Step 11 to Application ID, click OK and proceed to Deploy
20. Open the link http://<Application ID> in a browser and click Codelab and you should see the list of Twitter search results. Click refresh you will get the list of Twitter search results again.
21. Add these imports
 // retrieve the Twitter search last ID
DatastoreService datastoreService = DatastoreServiceFactory.getDatastoreService();  
try {
    Key lastIdPreviousKey = KeyFactory.createKey("LastId", "lastid");
    Entity lastIdPrevious = datastoreService.get(lastIdPreviousKey);
    last_id = (String) lastIdPrevious.getProperty("last_id");
} catch (EntityNotFoundException e) {
and replace
// save the new Twitter search last_id
if (i == 0) {
    Key lastIdKey = KeyFactory.createKey("LastId", "lastid");
    Entity lastId = new Entity(lastIdKey);
    lastId.setProperty("last_id", jResult.getString("id_str"));
22. Deploy again and refresh http://<Application ID> and click Codelab and you should still see the list of Twitter search results. But click refresh this time you will get "No new tweet" as now only new tweet will be fetched in every refresh.

Register users’ GCM Registration ID
23. Now we will create a new Servlet in App Engine Project to handle the storage of GCM registration ID. Select the package "my.devfestkl.codelab" and select "New -> Class"
24. Enter the Name "RegisterServlet", Superclass "javax.servlet.http.HttpServlet" and click Finish
25. Select Source -> Override/Implement Methods..., tick on doPost(HttpServletequest, HttpServletResponse) and click OK
26. Add these imports
super.doPost(req, resp);
DatastoreService datastoreService = DatastoreServiceFactory.getDatastoreService();
Entity regId = new Entity("RegId");
if(req.getParameter("regId")!=null && !req.getParameter("regId").equals("")) {
    regId.setProperty("reg_id", req.getParameter("regId"));
    resp.getWriter().append(regId + " successfully registered\r\n");
} else {
    resp.getWriter().append("No registration ID\r\n");      
27. Open web.xml in war/WEB-INF
28. Add these right after <web-app xmlns="......">


29. Deploy the Google App Engine application again and now we will shift to the creation of the Android client

Setup Android Application for GCM
30. Select New -> Android Application Project
31. Enter Application Name "Codelab Android", Package Name "my.devfestkl.codelab" and click Next
32. Complete the Configure Launcher Icon and click Next
33. BlankActivity is selected and click Next, modify the Title to "Codelab Android" and click Finish
34. Select the libs folder, right click and select Import
35. Select File System and click Next
36. Browse to <Android SDK Folder>/extras/google/gcm/gcm-client/dist and click OK
37. Tick gcm.jar and click Finish
38. Add these inside <manifest> in AndroidManifest.xml
[NOTE: There is a bug in the Syntax Highlighter that displays repeated tags as nested tags]

39. Add these inside <application> in AndroidManifest.xml
[NOTE: There is a bug in the Syntax Highlighter that displays repeated tags as nested tags]


Build Android Application classes
40. Create a new Java Class in Codelab Android Project by selecting New->Class
41. Enter Name "GCMIntentService", Superclass "" and click Finish
42. Add this inside <application> in AndroidManifest.xml

43. Open under src/my.devfestkl.codelab in Codelab Android Project
44. Add this at the top of the class with the SENDER ID from Step 5
public static String SENDER_ID = "YOUR SENDER ID"; 
45. Add this import
Add these into onCreate(Bundle savedInstanceState) below setContentView(R.layout.activity_main)
String regId = GCMRegistrar.getRegistrationId(this);
if (regId.equals("")) {
    GCMRegistrar.register(this, SENDER_ID);
46. Create a new Java Class in in Codelab Android Project by selecting New->Class
47. Enter Name "RegisterTask", Superclass "android.os.AsyncTask" and click Finish
48. Add these into the top of the class

private Context context;
public RegisterTask(Context context) {
     this.context = context;
49. Add these imports
Add these into doInBackground(String... params) before "return null"
String urlString = "http://<Application ID>";
try {
    URL url = new URL(urlString);
    HttpURLConnection connection = (HttpURLConnection)url.openConnection();
    String data = "regId=" + params[0];
    OutputStream os = connection.getOutputStream();
    InputStream is = connection.getInputStream();
    InputStreamReader isr = new InputStreamReader(is);
    BufferedReader reader = new BufferedReader(isr, 8);
    StringBuilder builder = new StringBuilder();
    String line = "";
    while((line = reader.readLine())!=null) {
    String response = builder.toString();
    if(response.contains("successfully registered")) {
     GCMRegistrar.setRegisteredOnServer(context, true);
} catch (MalformedURLException e) {
} catch (IOException e) {
50. Open under src/my.devfestkl.codelab in Codelab Android Project
51. Add this constructor at the top of the class
public GCMIntentService() {
52. Add this into onRegistered(Context arg0, String arg1)
new RegisterTask(this).execute(arg1);
53. Add these imports
54. Add this into onMessage(Context arg0, Intent arg1)
PendingIntent pi = PendingIntent.getActivity(arg0, 0, null, 0);
Builder builder = new NotificationCompat.Builder(this);
   .setContentTitle("New GCM Message")
   .setTicker("New GCM Message")
NotificationManager mgr = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);

Complete Google App Engine Application
55. Select the folder war/WEB-INF/lib in Codelab Google App Engine Project, right click and select Import
56. Browse to <Android SDK Folder>/extras/google/gcm/gcm-server/dist and click OK
57. Tick gcm-server.jar and click Finish
58. Select the folder war/WEB-INF/lib in Codelab Google App Engine Project, right click and select Import
59. Browse to <Android SDK Folder>/extras/google/gcm/gcm-server/lib and click OK
60. Tick json_simple-1.1.jar and click Finish
61. Right click on the project Codelab and select Properties
62. Select Java Build Path at the left bar and then select the Libraries tab
63. Click Add JARs and select gcm-server.jar from Codelab/war/WEB-INF/lib and click OK
64. Click Add JARs and select json_simple-1.1.jar from Codelab/war/WEB-INF/lib and click OK
65. Open in src/my.devfestkl.codelab in Codelab Google App Engine Project
66. Add these imports
import java.util.ArrayList;
67. Replace
// retrieve all GCM registration ID 
ArrayList<String> devices = new ArrayList<String>();     
Query query = new Query("RegId");
PreparedQuery preparedQuery = datastoreService.prepare(query);    
for (Entity regId : preparedQuery.asIterable()) {      
    String reg_id = (String) regId.getProperty("reg_id");
68. Replace
// send the GCM message
with (API Key from Step 8)
if(!devices.isEmpty()) {
 Sender sender = new Sender(<API KEY>);
    Message message = new Message.Builder()
      .addData("tweet", jResult.getString("text"))
    sender.send(message, devices, 5);
69. Deploy the Google App Engine application again
70. Select the Codelab Android project and then select Run->Run As->Android Application to run the Android Application either on an emulator or a device. For emulator, remember to add a Google Account first in Menu->Settings->Accounts & Sync->Add account->Google

Setup Cron for Google App Engine Application 71. Create a file cron.xml in war/WEB-INF in Codelab Google App Engine Project 72. Add these into cron.xml

  Perform Twitter search for new result every 2 minutes
  every 2 minutes

73. Deploy the Google App Engine application again

To Do:
  • Add security constraints to Codelab servlet so that only admin can refresh the page from browser
  • Modify the welcome page to remove the link to the Codelab servlet and add additional information to download the accompanying Android Application
  • Add an Unregister Servlet to remove GCM registration ID
  • Add an AsynTask in Android App to call Unregister Servlet in App Engine Server
  • Add a redirect to the home page for the Get request to both Register and Unregister Servlet
  • Add SQLite database to store results being pushed
  • Add a ListView to display the results from the SQLite database
  • Add a PendingIntent to the notification to show the ListView of results
  • Handle any error in MulticastResult returned by Sender.send()

Saturday, 10 December 2011

TEDxMMU 2011 Full-featured Embedded System Design with Smartphones

I am very honoured to be invited to present in TEDxMMU 2011, the independently organized TED event in Multimedia University. Presenting an interesting talk within 18 minutes is challenging and this is the only presentation that I ever did a rehearsal and I do fell good to complete it almost at the 18-minute mark. The details of the event are as follow:

Date:10 December 2011 (Saturday)
Time: 9.00am to 3.00pm
Venue: E-theater, Faculty of Creative Multimedia, Multimedia University, Cyberjaya

The synopsis of my talk:
"Smartphone has many features that can enhance the design of an embedded system such as Internet connection, voice recognition or camera captures. There are however a few problems that restrict such integration such as the high cost of a smartphone and limited direct data connection to a smartphone. With the introduction of Android Accessory, Android devices can be connected to a microcontroller via USB connection that provides identification and bulk transfer via input/output streams. Foreseeing more low cost Android devices and the ease of getting hardware components for developing Android Accessory, there will be an increase of integration of Android devices into an embedded system in various areas such as robotics, consumer products, medical products and educations."

The video of my presentation is supposed to be recorded and published later but it is not available due to technical problems. Some of the TEDxMMU 2011 videos are however available. However this is a great event for me.

Tuesday, 4 October 2011

Android-powered Remote Controlled Blimp with Video Surveillance

The project "Remote Controlled Blimp with Video Surveillance" is a joint project between several Multimedia University academicians as an Interactive Installation for the DA+C Festival 2011 (Digital Art and Cultural Festival) mainly from 15 to 17 July 2011 at Suffolk House, George Town, Penang, Malaysia. The project is named "FRANC" as a tribute to Captain Francis Light (notice that the name Francis Light can be separated into "Franc is Light", hence the name of "Franc" which refers to the Helium-filled blimp which of course is lighter than the air, therefore "is light". The main focus of the project is to continuously provides the birds' eye video feed of the interior of Suffolk House.


The indoor blimp is mainly based on Blimpduino project from DIY Drones. The wireless control is however not done using regular radio-controller gears but via BlinkGear BlinkRC, so that the control signals can be sent directly from a PC via UDP data packet. The EyeCam 2.4GHz wireless video transmitter provides the aerial video which is captured by a USB TV Capture device and eventually streamed in VLC player on the main PC.

FRANC V1 with BlinkRC and EyeCam 

During initial testing, there are problems discovered with the first design. The EyeCam wireless video requires line-of-sight and is very susceptible to interference (various 2.4GHz signals from WiFi, Bluetooth etc.). The BlinkRC also sometimes fails to connect but eventually we discover that there is a loose connection on the BlinkRC PCB board and is finally fixed. However FRANC version 2 is still being developed as a backup.

FRANC V2 with Android and IOIO

The version 2 is mainly based on Android, which covers both the control and the video surveillance: 
  • An Android application has been developed to receive the exact same UDP data packets as in Version 1 to drive the blimp. The PWM signals to drive the motors are sent out from an IOIO board which connects to the Android phone via USB using the ADB protocol.
  • An existing Android application "IP Webcam" is used to stream the video capture. 

The major problem with this design is the larger weight of an Android device (HTC Legend) with USB cable which requires more blimp envelopes.


Further improvement is focus mainly on reducing the weight of the payload:

  • Using the lightest Android phone possible (Sony Ericsson Xperia X10 Mini which weights only 88g)
  • Redesign the circuit board by integrating the Blimpduino circuit and the IOIO circuit.
  • Reduce the length of the USB cable
Further advancement is to add interactivity to the blimp for autonomous movement as the remote control is kind of difficult due to the combination of winds, momentum and human reaction. For example the WeBlimp  project shown in the video below:

Monday, 3 October 2011

Integration of Android and NFC into Home Entertainment System

"Integration of Android and NFC into Home Entertainment System" is one of the Multimedia University Faculty of Engineering Final Year Project proposal for session 2011/12. The project is inspired by Google IO 2011 Day 1 keynote about the Android@Home as shown below:

The main feature of the system will be described as the scenario below:
  • Once a selected music album cover attached with NFC (Near Field Communication) tag is brought near to an embedded NFC reader in a home speaker system or an Android phone with NFC capability (Nexus S), the home entertainment system will start playing the song, and the Android phone will display the information of the album. 
The project will be divided into two parts:
  1. The development of the embedded NFC reader in a home speaker system using either a USB NFC reader such as ACR122U NFC Contactless Smart Card Reader connected to a Windows Presentation Foundation application on a PC or an embedded NFC module such as SM130 13.56 MHz RFID Mifare Module connected to a network enabled Arduino or mbed embedded system. The NFC reader will continuously waiting to read an NFC tag brought near to it and immediately send the data read to a home entertainment system to trigger the playing of an album. 
  2. The development of the Android application on an Android device that waiting to read from an NFC tag to trigger the playing of an album similar to part 1 and to display the information retrieved from the home entertainment system about the album.
Use of SM130 13.56MHz Mifare Module in my previous project