Wednesday, February 22, 2012

Second Look at Android Mobile Development

Lately, I've been working on an Android project using the PhoneGap and JQuery. Just want to share some notes of the development I wrote so far.

We use PhoneGap as a packaging framework integrating the native OS with the mobile web application. The mobile framework allows web developers to natively target all smartphones with a single codebase (JavaScript, HTML and CSS) by using its API and connecting to an embedded WebView or WebKit on the device. We use JQuery Mobile as a web application framework to build the web screens and logics.

After a few weeks of Android development, there are couple of advantages I found:
1. Great and easy integration with 3rd party plugins
2. Fast reloading both on simulators and on devices
3.

An example of PhoneGap and ChildBrowser plugin:
Step 1. Set up the ChildBrowser plugin following this page:
https://github.com/phonegap/phonegap-plugins/tree/master/Android/ChildBrowser

Step 2. Sample Codes in index.html

<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no;" />
<meta charset="utf-8">


<!-- iPad/iPhone specific css below, add after your main css >
<link rel="stylesheet" media="only screen and (max-device-width: 1024px)" href="ipad.css" type="text/css" />
<link rel="stylesheet" media="only screen and (max-device-width: 480px)" href="iphone.css" type="text/css" />
-->
<!-- If your application is targeting iOS BEFORE 4.0 you MUST put json2.js from http://www.JSON.org/json2.js into your www directory and include it here -->
<script type="text/javascript" charset="utf-8" src="phonegap-1.3.0.js"></script>
<script type="text/javascript" charset="utf-8" src="childbrowser.js"></script>
<!-- <script src="http://code.jquery.com/jquery-1.5.2.min.js"></script> -->
<!-- <script src="http://code.jquery.com/mobile/1.0a4.1/jquery.mobile-1.0a4.1.min.js"></script> -->
<script type="text/javascript">
function onBodyLoad()
{
document.addEventListener("deviceready",onDeviceReady,false);
}
/* When this function is called, PhoneGap has been initialized and is ready to roll */
/* If you are supporting your own protocol, the var invokeString will contain any arguments to the app launch.
see http://iphonedevelopertips.com/cocoa/launching-your-own-application-via-a-custom-url-scheme.html
for more details -jm */
function onDeviceReady()
{
checkConnection();
}

function showPage()
{
var val = "http://www.google.com"
window.plugins.childBrowser.showWebPage(val, { showLocationBar: true });

}
</script>
</head>
<body onload="onBodyLoad()">
<br />
<ol>
<p> Show the web page </p>
<button onclick="showPage()">Go to web page</button>
</ol>
</body>
</html>


Enjoy Android Developing!

Wednesday, December 21, 2011

Android Development

I have been getting familiar with the Android Development lately with the help of PhoneGap. Just want to share a simple app integrating with the native Android OS. The application has the simple functionality as creating contacts, removing contacts and looking for contacts.

I ran into some configuration issues in the beginning, but after reading the article: http://simonmacdonald.blogspot.com/2011/09/saving-contacts-with-phonegap-android.html, my setting issues are resolved. Thanks to Simon.

Codes in index.html:
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no;" />
<meta charset="utf-8">
<script type="text/javascript">
function onBodyLoad()
{
document.addEventListener("deviceready",onDeviceReady,false);
}
/* When this function is called, PhoneGap has been initialized and is ready to roll */
function onDeviceReady()
{
console.log("PhoneGap is working")
}
function createContact(firstName, lastName)
{
// create a new contact object
var contact = navigator.contacts.create();
contact.displayName = "Plumber";
contact.nickname = "Plumber"; //specify both to support all devices

// populate some fields
var name = new ContactName();
name.givenName = firstName.value;
name.familyName = lastName.value;
contact.name = name;

// save to device
contact.save(onSuccess,onError);
}
function onSuccess(contact)
{
alert("Save Success");
};

function onError(contactError)
{
alert("Error = " + contactError.code);
};
function onFindSuccess(contacts)
{
alert("Find Success");
var string="";
for (var i=0; i<contacts.length; i++) {
string = string + contacts[i].name.givenName + " " +contacts[i].name.familyName + "\n";
}
alert(string);
};

function onFindError(contactError)
{
alert("Find Error = " + contactError.code);
};
function findContact()
{
// specify contact search criteria
var options = new ContactFindOptions();
options.filter=""; // empty search string returns all contacts
options.multiple=true; // return multiple results
filter = ["name"]; // return contact.name field

// find contacts
navigator.contacts.find(filter, onFindSuccess, onFindError, options);
}
function removeContact(removeFirstName, removeLastName){
options = new ContactFindOptions();
//options.filter=removeFirstName.value;
options.filter=removeFirstName.value;
navigator.contacts.find(["name.givenName","displayName"], onRemoveFindSuccess, onFindError, options);
}
function onRemoveFindSuccess(contacts)
{
contacts[0].remove(removeFindSuccess, removeFindError);
}
function removeFindSuccess()
{
alert("Contact removed.");
}
function removeFindError(error)
{
alert("Remove Error: " +error)
}
</script>
</head>
<body onload="onBodyLoad()">
<br />
<ol>
<p> Welcome to index.html </p>
<p> First Name: </p>
<input type="text" name="firstName" id="firstName" value=""/>
<p> Last Name: </p>
<input type="text" name="lastName" id="lastName" value=""/>
<button onclick="createContact(firstName, lastName);">Add Contact</button><br>
<button onclick="findContact();">Find Contact</button><br>
<p> First Name: </p>
<input type="text" name="removeFirstName" id="removeFirstName" value=""/>
<button onclick="removeContact(removeFirstName,removeLastName);">Remove Contact</button> <br>
</ol>
</body>
</html>

Enjoy!

Wednesday, April 27, 2011

BES-Push: Setup Trusted Connections to BlackBerry MDS

To permit push applications to make trusted connections (SSL) to a BlackBerry MDS Connection Service, some preparation steps are required to be done beforehand. Follow the setup procedure as follows:

1. Enable Push Encryption from the BlackBerry Administration Service

· Open the BlackBerry Administration Service Web Console

· Go to “Servers and Components” section

· Expand “BlackBerry Solution Topology”

· Expand “Component View” under “BlackBerry Domain”

· Expand “MDS Connection Service”

· Click on the MDS instance to which your push application is connected

· In the “Instance information” tab, make sure the port number which the BlackBerry devices open to listen to the push messages is defined under the “Ports enabled for reliable pushes” section

· In the “Instance information” tab, enable “Push Encryption” under the “Access Control” section by setting the value to “Yes”

· Switch to the “General” tab, make sure the “Web server listen port” and “Web server SSL listen port” are defined and there are no conflicts with the port numbers

· Restart the MDS-CS instance

· Notes: More information is available at: http://docs.blackberry.com/en/admin/deliverables/12107/Restricting_push_content_users_receive_on_devices_268662_11.jsp#Restrict_push_apps_from_sending_data_to_devices_547121_11

2. Import the BlackBerry MDS Connection Service to the key store of a push application by following this instruction:

· http://docs.blackberry.com/en/admin/deliverables/12107/Allowing_push_apps_trusted_connections_to_MDSCS_268652_11.jsp

· Notes:

i. For the last part in the instruction, which is to import the certificate to the push application, make sure the certificate is imported to the key store of the Java JRE which is being used by your push application

ii. In the step of adding the certificate to the key store, make sure you have the permission to change the key store file

iii. If the certificate is not correctly imported, a similar error will be thrown as “Unable to find valid certification path to requested target

Now the push application is able to send SSL push request to the BlackBerry devices through MDS.

Tuesday, April 12, 2011

BlackBerry BIS Push Samples

The BlackBerry Push Service is a powerful tool of the real-time experience of BlackBerry smartphones. It offers an efficient and reliable way of sending information to your users. It also allows your application to process information in the background and alert users.

RIM provided some sample push applications for both the BES and BIS cases. Since BIS case is more complicated, I will elaborate the procedure here in this post. I will also mention some frequent problems the developers experienced and the solutions or workarounds for those issues.

1. Install and configure a MySQL database following this instruction: http://docs.blackberry.com/en/developers/deliverables/24182/Installing_MySQL_in_Windows_1241571_11.jsp

2. Download JDBC driver following this instruction:

http://docs.blackberry.com/en/developers/deliverables/24182/Download_JDBC_driver_for_MySQL_1220461_11.jsp

3. Install the BlackBerry Push SDK following this instruction:

http://docs.blackberry.com/en/developers/deliverables/24182/Run_the_BPSS_setup_application_1229036_11.jsp

4. Verify the push server is setup correctly following this instruction:

http://docs.blackberry.com/en/developers/deliverables/24182/Verifying_that_push_server_configured_correctly_1227911_11.jsp

5. Install the sample push-enabled application on the BlackBerry device following this instruction:

http://docs.blackberry.com/en/developers/deliverables/24182/Install_the_client-side_sample_app_to_device_1015009_11.jsp

6. From Step 5, the settings in the device-side application are:

(1) Port: the push port number in RIM’s registration email

(2) App ID: the App ID in RIM’s registration email

(3) BPAS URL: http://pushapi.eval.blackberry.com (already defined in the settings)

(4) Content Provider URL: https://:8443/sample-push-initiator

7. When you register your device to the push server, if you get an error:

Error: Request to register failed. Caused by java.io.IOException: Network operation [Subscribe] failed. Make sure that Content Provider URL is accessible.

Reason: The Content Provider URL is not accessible from the device.

Solutions:

1. First of all, try the content provider url in your device browser, make sure it is accessible.

2. If it is not accessible, there are some workarounds you can try:

(1) Workaround 1: Make your content provider URL public, for example: https://abcsystems.com:8443/sample-push-initiator

(2) Workaround 2: For development purposes, if your BlackBerry device is registered on BES, you can try the following steps:

i. Step 1: Add the SSL certificate to your MDS following this instruction: http://www.blackberry.com/btsc/search.do?cmd=displayKC&docType=kc&externalId=KB11623

ii. Step 2: Make sure after the certificate is added to the MDS, you can access the content provider URL from your BlackBerry browser

iii. Step 3: Extract the “sample-push-enabled-app” source jar and create a project with the same source codes under your development environment

iv. Step 4: Change the codes in “PushUtils.java” as follows:

private static String getConnectionSuffix() {

return ";deviceside=false";}

Notes: This workaround will make sure you use the MDS to connect the content provider URL which is a local server.

v. Setp 5: Rebuild the sample-push-enabled-app and download it to your BES-enabled BlackBerry device. Configure the settings following:

http://docs.blackberry.com/en/developers/deliverables/24182/Install_the_client-side_sample_app_to_device_1015009_11.jsp

Now you should be able to run the sample-push-initiator on your local server and the sample-push-enabled-app on your device with the push-and-receive ability setup.

Enjoy!

Monday, December 6, 2010

Synchronize BlackBerry Emails with Exchange Server

Lately, I implemented the function that given the native emails on BlackBerry, fetch the email attachments in the email from the Exchange Server.

Input: Emails w/ attachments on BlackBerry (The email account is on the Exchange Server)

Output: Actual attachments of the email

Complexity:
1. The attachments in an email on BlackBerry are not download to the device, therefore there is no good method to get the actual attachments through RIM API.

2. RIM API provides limited access to the properties of emails, what you can get are basically listed in the link: http://www.blackberry.com/developers/docs/4.6.0api/net/rim/blackberry/api/mail/Message.html

3. According to different exchange server versions (mainly 2003 and 2007), there are different protocols and require different transformation format. For Exchange 2003, the protocol is WebDAV which stands for Web-based Distributed Authoring and Versioning. The transformation from Exchange Message to the DAV Message that the protocol recognizes (through SQL). For Exchange 2007, the protocol is EWS which stands for Exchange Web Services. The transformation from Exchange Message to the EWS Message that the protocol recognizes (through SOAP and XML).

Possible Solutions:
Pass in a set of attributes which can be reached from RIM API (not Message ID since that is only good for BlackBerry.) and are also the same with the email record on Exchange Server. Once targeted the correct email, fetch the attachments from the Exchange Server.

Final Solutions:
Attributes passed in: Subject, Sent Time and From.

Technical requirements:
1. RIM API
2. Exchange Server and Protocols (both WebDAV and EWS)

Reference:
1. http://msdn.microsoft.com/en-us/library/bb204119.aspx
2. http://en.wikipedia.org/wiki/WebDAV

Thursday, September 23, 2010

Book Review: How to Win Friends and Influence People

《How to Win Friends and Influence People》 by Dale Carnegie

1. The importance of human relationship: "Even in the field of Engineering, about 15 percent of one's financial success is due to one's technical knowledge and about 85 percent is due to skill in human engineering--- to personality and the ability to lead people."

2. "The person who has technical knowledge plus the ability to express ideas, to assume leadership, and to arouse enthusiasm among people--- that person is headed for higher earning power."

3. Professor William James of Harvard once said "Compared to what we ought to be, we are only half awake. We are making use of only a small part of our physical and mental resources. Starting the thing broadly, the human individual thus lives far within his limits. He posesses powers of various sorts which he habitually fails to use."

4. "The great aim of education is not knowledge but action."

5. Ask yourself on a weekly basis:
"What mistakes did I make that time?"
"What did I do that was right--- and in what way could I have imporved my performance?"
"What lessons can I learn from that experience?"

6. "Ninety-nine times out of a hundred, people don't criticize themselves for anything, no matter how wrong it may be."

7. "Let's realize that the person we are going to correct and condemn will probably justify himself or herself, and condemn us in return."

8. "When dealing with people, let us remember we are not dealing with creatures of logic. We are dealing with creatures of emotion, creatures bristling with predudices and motivated by pride and vanity."

9. "Instead of condemning people, let's try to understand them. Let's try to figure out why they do what they do."

10. Sigmund Freud said that "Everything you and I do springs from two motives: the sex urge and the desire to be great."

11. Lincoln once said "Everybody likes a compliment."

12. "Don't be afraid of enemies who attack you. Be afraid of the friends who flatter you."

13. "In our interpersonal relations we should never forget that all our associates are human beings and hunger for appreciation."

14. "Let's cease thinking of our accomplishments, our wants. Let's try to figure out the other person's good points. Then forget flattery. Give honest, sincere appreciation."

15. "The only way on earth to influence other people is to talk about what they want and show them how to get it."

16. "Action springs out of what we fundamentally desire and the best piece of advice which can be given to would-be persuaders, whether in business, in the home, in the school, in politics, is: First, arouse in the other person an eager want. He who can do this has the whole world with him. He who cannot walks a lonely way."

17. "Tomorrow you may want to persuade somebody to do something. Before you speak, pause and ask yourself: 'How can I make this person want to do it?'"

18. Henry Ford once said, "If there is any one secret of success, it lies in the ability to get the other person's point of view and see things from that person's angle as well as from your own."

19. "The world is full of people who are grabbing and self-seeking. So the rare individual who unselfishly tries to serve other has an enormous advantage."

20. "People who can put themselves in the place of other people, who can understand the workings of their minds, need never worry about what the future has in store for them."

Wednesday, September 1, 2010

What I learned about BB Email Structure lately

Lately, I've been fixing a really sneaky bug and today I finally fixed it! It has something to do with the email structure and also the new os version of blackberry 6.

1. Typical Email Structure of a HTML email


2. Timing of the corresponding "text/plain" content being loaded
When the email first comes to the device, if you want to access the content of the email, you need to use Transport.more() to request more information from the server. I notice that for the peer-part of "text/html", there is a "text/plain" part comes with html mimebodypart. However, when you use Transport.more(BodyPart, true) to get the information in the "text/plain" mimebodypart, it will take approximately 5 seconds to load the content to the bodypart. Therefore, in your program, you need to wait longer for the content fetching.

3. Always deep check the content
Moreover, you need to double check the content when there is some content in the bodypart to make sure the content is not just spaces.

Reference:
1. How to- Access HTML email messages
http://www.blackberry.com/knowledgecenterpublic/livelink.exe/fetch/2000/348583/800332/800698/How_To_-_Access_HTML_email_messages.html?nodeid=1443037&vernum=0

2. One useful thread in a BB Forum
http://supportforums.blackberry.com/t5/Java-Development/Extract-Plain-Text-from-HTML-Email/td-p/184499