Tuesday, December 23, 2014

Deploy cordova apps to google play store.


0. Before release
Change version in the config.xml.
<widget id="com.yourdomain.yourapp" version="0.0.2" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
Make sure the same version in AndroidManifest.xml.
And android:debuggable should be false.
<manifest android:hardwareAccelerated="true" android:versionCode="2" android:versionName="0.0.2" package="com.yourdomain.yourapp" android:windowSoftInputMode="adjustPan" android:debuggable="false" xmlns:android="http://schemas.android.com/apk/res/android">

1. create keystore file

http://developer.android.com/tools/publishing/app-signing.html#cert

$ keytool -genkey -v -keystore [Key store file name] -alias [alias name] -keyalg [key algorithm type] -keysize [key size] -validity [expire days]

<example>
$ keytool -genkey -v -keystore mysampleappkey.keystore -alias mysampleapp -keyalg RSA -keysize 2048 -validity 18250

2. Ant configuration file
Add these lines to ant.properties file under platforms/android/.
If you are using windows based path, you have to use double slashes, \\ instead of \.

key.store=C:\\mykeyfolder\\my-release-key.keystore
key.alias=app_name
3. Build app
$ cordova build android

4. Make apk in release mode
$ cd platforms/android
$ ant release
Enter keystore and alias password in the middle of the process.
You could ignore warning messages.

5. Sign your app with your private key

http://developer.android.com/tools/publishing/app-signing.html#releasemode

$ cd bin
$ jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore my-release-key.keystore my_application.apk alias_name

Enter keystore password in the middle of the process.

6. Verify your apk is signed.
$ jarsigner -verify -verbose -certs my_application.apk

7. Align the final apk package.
$ zipalign -v 4 your_project_name-unaligned.apk your_project_name.apk

8. Prepare images.
a. At least two screen shots of your application.
b. One high resolution icon.(512*512, 32bit png with alpha)
c. Feature Graphic.(1024w*500h, jpg or 24bit png with no alpha)
You need google account to sign in to Google play developer console.

9. Upload to google play store.
Please refer to this instuctions.
https://developer.android.com/distribute/googleplay/developer-console.html

a. Sign in to Google Play Developer Console.
b. Go to All applications All applications and click +Add new application button.
c. Select language and add application title, then click Upload APK button.
d. Select where to upload.
You can setup beta or alpha testing to get feedbacks from limited groups before launch your app to production.

For Beta and Alpha testing, you need to invite testers via  Google Group or Google+ Community.
https://support.google.com/googleplay/android-developer/answer/3131213?hl=en

e. Upload your app.

f. Go to Store Listing menu and fill out the fields.

Fields marked with * is mandate fields and you can check any missing fields by clicking 'Why can't I publish?'.
   
Add at least two screen shots.
 Upload a high resolution icon and feature graphic.
Additional infos... 



g. Go to Pricing & Distribution menu and fill out the fields.
Select countries where you want to distibute.
Check the agreements of Content guidlines and US export laws.

h. Now, you can publish your app to google play store.
You can install your app from this path.
https://play.google.com/apps/testing/[your package name].



Friday, December 5, 2014

using contact in cordova

Please refer to this page.. http://docs.phonegap.com/en/2.9.0/cordova_contacts_contacts.md.html

1. add plugin
$ cordova plugin add org.apache.cordova.contacts
2. Permissions

Android

app/res/xml/config.xml

<plugin name="Contacts" value="org.apache.cordova.ContactManager" />

app/AndroidManifest.xml

<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />

iOS

config.xml

<plugin name="Contacts" value="CDVContacts" />
3. make codes

contacts.create

Returns a new Contact object.
var contact = navigator.contacts.create(properties);

Quick Example

var myContact = navigator.contacts.create({"displayName": "Test User"});

contacts.find

Queries the device contacts database and returns one or more Contact objects, each containing the fields specified.
navigator.contacts.find(contactFields, contactSuccess, contactError, contactFindOptions);

Quick Example

function onSuccess(contacts) {
    alert('Found ' + contacts.length + ' contacts.');
};
function onError(contactError) {
    alert('onError!');
};
// find all contacts with 'Bob' in any name field
var options      = new ContactFindOptions();
options.filter   = "Bob";
options.multiple = true;
var fields       = ["displayName", "name"];
navigator.contacts.find(fields, onSuccess, onError, options);

Contact

Contains properties that describe a contact, such as a user's personal or business contact.

Properties

  • id: A globally unique identifier. (DOMString)
  • displayName: The name of this Contact, suitable for display to end-users. (DOMString)
  • name: An object containing all components of a persons name. (ContactName)
  • nickname: A casual name by which to address the contact. (DOMString)
  • phoneNumbers: An array of all the contact's phone numbers. (ContactField[])
  • emails: An array of all the contact's email addresses. (ContactField[])
  • addresses: An array of all the contact's addresses. (ContactAddress[])
  • ims: An array of all the contact's IM addresses. (ContactField[])
  • organizations: An array of all the contact's organizations. (ContactOrganization[])
  • birthday: The birthday of the contact. (Date)
  • note: A note about the contact. (DOMString)
  • photos: An array of the contact's photos. (ContactField[])
  • categories: An array of all the user-defined categories associated with the contact. (ContactField[])
  • urls: An array of web pages associated with the contact. (ContactField[])

Methods

  • clone: Returns a new Contact object that is a deep copy of the calling object, with the id property set to null.
  • remove: Removes the contact from the device contacts database, otherwise executes an error callback with a ContactError object.
  • save: Saves a new contact to the device contacts database, or updates an existing contact if a contact with the same idalready exists.

Save Quick Example

function onSuccess(contact) {
    alert("Save Success");
};
function onError(contactError) {
    alert("Error = " + contactError.code);
};
// 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 = "Jane";
name.familyName = "Doe";
contact.name = name;
// save to device
contact.save(onSuccess,onError);

Clone Quick Example

    // clone the contact object
    var clone = contact.clone();
    clone.name.givenName = "John";
    console.log("Original contact name = " + contact.name.givenName);
    console.log("Cloned contact name = " + clone.name.givenName);

Remove Quick Example

function onSuccess() {
    alert("Removal Success");
};
function onError(contactError) {
    alert("Error = " + contactError.code);
};

    // remove the contact from the device
    contact.remove(onSuccess,onError);

ContactAddress

Contains address properties for a Contact object.

Properties

  • pref: Set to true if this ContactAddress contains the user's preferred value. (boolean)
  • type: A string indicating what type of field this is, home for example. (DOMString)
  • formatted: The full address formatted for display. (DOMString)
  • streetAddress: The full street address. (DOMString)
  • locality: The city or locality. (DOMString)
  • region: The state or region. (DOMString)
  • postalCode: The zip code or postal code. (DOMString)
  • country: The country name. (DOMString)

4. Additional things...

Methods

Arguments

Objects

Cordova plugin list

  • http://cordova.apache.org/docs/en/4.0.0/guide_cli_index.md.html
  • Basic device information (Device API):
    $ cordova plugin add org.apache.cordova.device
  • Network Connection and Battery Events:
    $ cordova plugin add org.apache.cordova.network-information
    $ cordova plugin add org.apache.cordova.battery-status
  • Accelerometer, Compass, and Geolocation:
    $ cordova plugin add org.apache.cordova.device-motion
    $ cordova plugin add org.apache.cordova.device-orientation
    $ cordova plugin add org.apache.cordova.geolocation
  • Camera, Media playback and Capture:
    $ cordova plugin add org.apache.cordova.camera
    $ cordova plugin add org.apache.cordova.media-capture
    $ cordova plugin add org.apache.cordova.media
  • Access files on device or network (File API):
    $ cordova plugin add org.apache.cordova.file
    $ cordova plugin add org.apache.cordova.file-transfer
  • Notification via dialog box or vibration:
    $ cordova plugin add org.apache.cordova.dialogs
    $ cordova plugin add org.apache.cordova.vibration
  • Contacts:
    $ cordova plugin add org.apache.cordova.contacts
  • Globalization:
    $ cordova plugin add org.apache.cordova.globalization
  • Splashscreen:
    $ cordova plugin add org.apache.cordova.splashscreen
  • Open new browser windows (InAppBrowser):
    $ cordova plugin add org.apache.cordova.inappbrowser
  • Debug console:
    $ cordova plugin add org.apache.cordova.console

Friday, November 7, 2014

Basic http server authentication from mobile app via ajax

1. script for ajax 
function make_base_auth(user, password) {
  var tok = user + ':' + password;
  var hash = btoa(tok);
  return "Basic " + hash;
}
$.ajax({
type: 'POST',
beforeSend: function (xhr){  xhr.setRequestHeader('Authorization', make_base_auth("guest", "guest"));   },
xhrFields: {
withCredentials: true
}
,  crossDomain: true,
url: 'http://www.gtatrade.ca/mobiletest',
data: ({name: "aaa"}),
success: function(data){alert(data.name);},
error: function(e, x, settings, exception){alert("error!!" + "," + e.staus + ","  + e.responseText + ","  + x + ","  + settings + ","  + exception);},
dataType: 'json'
});

*** If you send header every time, use ajaxSetup like below.
$.ajaxSetup({
    beforeSend: function(xhr) {
        xhr.setRequestHeader('Authorization', make_base_auth("guest", "guest"));
    }
xhrFields: {
withCredentials: true
}
,  crossDomain: true,
});

2. Server php
if (!isset($_SERVER['PHP_AUTH_USER'])) {
header("Access-Control-Allow-Origin: *"); // required for cross domain .. 
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE");
header("Access-Control-Allow-Headers: Authorization");
    header('WWW-Authenticate: Basic realm="My Realm"');
    header('HTTP/1.0 401 Unauthorized');
    echo 'Text to send if user hits Cancel button';
    exit;
} else {
header("Access-Control-Allow-Origin: *");  // required for cross domain ..
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE");
header("Access-Control-Allow-Headers: Authorization");
    $output = array("name"=>$_SERVER['PHP_AUTH_USER'], "pass"=>$_SERVER['PHP_AUTH_PW']);
    echo json_encode($output);
}

Some tips for jquery mobile or cordova

1. Phone call
- on the page
<a href="tel:+14163334444" rel="external" class="ui-btn ui-icon-phone ui-btn-icon-left phonelink">(416) 333-4444</a>

- add these linbes to config.xml
  <access origin="tel:*" launch-external="yes" />
  <access origin="mailto:*" launch-external="yes" />

2. Save properties to file
set :
window.localStorage.setItem("name", "yourname");
get:
var name = window.localStorage.getItem("name");

3. push footer to bottom
apply this style...

[data-role=page]{height: 100% !important; position:relative !important;}
[data-role=footer]{bottom:0; position:absolute !important; top: auto !important; width:100%;}


Thursday, November 6, 2014

Add Google map

Please refer to this link....
http://demos.jquerymobile.com/1.4.0/map-geolocation/

I'm going to do these things in this example.
- Add google map to my app.
- Get my current location and add marker.
- Show information window with the address when the marker is clicked.
- Show the boundary position of the google map when a button is clicked.

1. Prepare Page
<html>
    <head>
<link rel="stylesheet" href="css/jquery.mobile-1.4.4.min.css" />
<style>
#map-page, #map-canvas { width: 100%; height: 93%; padding: 1px; }
</style>
<script src="js/jquery-1.11.1.min.js"></script>
<script src="js/jquery.mobile-1.4.4.min.js"></script>
<script type="text/javascript" src="cordova.js"></script>
<!-- import google map js -->
<script src="http://maps.google.com/maps/api/js?sensor=false"></script>
    </head>

<div data-role="page" id="map-page" data-url="map-page">
<div data-role="header">
<h1>Google map demo</h1>
<a href="#" id='showBounds'  class="ui-btn ui-icon-search ui-btn-icon-left">Show</a>
</div>
    <div role="main" class="ui-content" id="map-canvas">
        <!-- map loads here... -->
    </div>
</div>
</html>

2. Prepare Script
<script>
/*
 * Google Maps documentation: http://code.google.com/apis/maps/documentation/javascript/basics.html
 * Geolocation documentation: http://dev.w3.org/geo/api/spec-source.html
 */
 var bounds;
 var map;
$( document ).on( "pageinit", "#map-page", function() {
    var defaultLatLng = new google.maps.LatLng(34.0983425, -118.3267434);  // Default to Hollywood, CA when no geolocation support
    if ( navigator.geolocation ) {
        function success(pos) {
            // Location found, show map with these coordinates
//alert(pos.coords.latitude);
            drawMap(new google.maps.LatLng(pos.coords.latitude, pos.coords.longitude));
        }
        function fail(error) {
            drawMap(defaultLatLng);  // Failed to find location, show default map
        }
        // Find the users current position.  Cache the location for 5 minutes, timeout after 6 seconds
        navigator.geolocation.getCurrentPosition(success, fail, {maximumAge: 500000, enableHighAccuracy:true, timeout: 6000});
    } else {
        drawMap(defaultLatLng);  // No geolocation support, show default map
    }
    function drawMap(latlng) {
        var myOptions = {
            zoom: 15,
            center: latlng,
            mapTypeId: google.maps.MapTypeId.ROADMAP
        };
        map = new google.maps.Map(document.getElementById("map-canvas"), myOptions);
        // Add an overlay to the map of current lat/lng
        var marker = new google.maps.Marker({
            position: latlng,
            map: map,
            title: "Greetings!",
        });

var contentString = '<div id="content"><h3>Info</h1></div>';
var infowindow = new google.maps.InfoWindow({
content: contentString
});

google.maps.event.addListener(marker, 'click', function() {
showAddressFromLatLang(map,marker);
        });

google.maps.event.addListener(map, 'bounds_changed', function() {
           bounds = map.getBounds();
});
// var b = map.getBounds();
// alert(b);
//alert(b.getNorthEast().lat());
// alert(b.getCenter().lat());
    }

});
function showAddressFromLatLang(map,marker){
var pos = marker.getPosition();
var geocoder = new google.maps.Geocoder();
geocoder.geocode( { 'latLng': pos}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if(results[0]) {
var infowindow0 = new google.maps.InfoWindow({
content: '<div id="content"><h3>' + results[0].formatted_address + '</h3></div>'
});
infowindow0.open(map,marker);
}
}else{
alert("Geocode was not successful     for the following reason: " + status);
}
});
}
$( "#showBounds" ).click(function() {
alert(bounds); // .getSouthWest());
});
</script>

3. Edit config.xml
- Add these lines to config.xml

<feature name="Geolocation">
<param name="ios-package" value="CDVLocation" />
    <param name="android-package" value="org.apache.cordova.GeoBroker" />
</feature>

4. Add permission for android
- Add these lines to AndroidManifest.xml

    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

5. Run...
 $ cordova run android
6. Result Screen shot

When 'Show' button is clicked you can see the boundary positions.