SDK default key was used. To publish developer own key should be used with Registration file.
If you submit an app to Tizen (Samsung Seller) and get this rejection back:
<Defect>
SDK default key was used. To publish developer own key should be used with Registration file
For more information, refer to IDE > Help Contents > Generating a certificate request
Or, Help Contents > Getting Started with Tizen wearable > Development Environment > Tizen SDK for wearable > Certificates
<Procedure>
<Expected Result>
Then it means that your Tizen app was not signed.
The procedure is as follows:
Generating a Certificate Request
There are 2 ways to generate a certificate request: you can make a certificate request from scratch, or you can use your existing Android keystore. When you develop a companion type application, the second option is better, since you must use the same author certificate for both the host and wearable application.
To make a certificate request from scratch to obtain an author certificate:
- Click the
button on the Tizen IDE for Wearable toolbar.
The Generate Certificate Request dialog opens.
-
Enter the following information:
- Mandatory information
- Name
- Private key password
- Password confirm
- Developer type
- Privilege level
- DUID (Device Unique Identifier)
- Optional information
- Country
- State
- City
- Organization
- Department
- Mandatory information
To use your existing Android keystore to obtain an author certificate:
- Click the
button on the Tizen IDE for Wearable toolbar.
The Import Android Keystore and Generate Certificate Request dialog opens.
-
Enter the following information:
- Mandatory information
- Alias
Click Import, input the keystore with the password, and select the right alias.
- Private key password
- Name
- Developer type
- Privilege level
- DUID (Device Unique Identifier)
- Alias
- Optional information
- Country
- State
- City
- Organization
- Department
- Mandatory information
Getting the DUID
To get the DUID (Device Unique Identifier):
- Connect your device to your host computer or launch the Emulator.
- In the Connection Explorer, check that the connected device or Emulator is visible.
- Select the device or Emulator, and click Properties.
The DUID is visible on the Info panel
Sending a Certificate Request
You must first generate the developer key used for application signing and then send it for signing to the Samsung Developer Center. The following figure illustrates the registration process.
Figure: Sending a certificate request using PGP
To get the key signed, you must be encrypt it and send it to Samsung Developer Center using PGP (Pretty Good Privacy) encryption. You can generate your own PGP key using a PGP support tool. The tool normally generates a key pair consisting of a private key and public key.
Send your public key to gear2.sec@samsung.com with the encrypted request. After the Samsung Developer Center has signed it, you receive the registration XML file. Use your private key to decrypt the registration file.
The process and encryption tool required to generate the developer key vary depending on your operating system:
Signing the Developer Key (Windows®)
To send a developer key request to the Samsung Developer Center, you have to first encrypt the keys and email them using PGP (Pretty Good Privacy).
To send a developer key request to the Samsung Developer Center:
- To download the Gnu Privacy Assistant (GPA) PGP support application, go to www.gpg4win.org and download the GPA installer (gpg4win.exe). In the setup dialog, select the GPA component.
| Other PGP tool support applications, such as Kleopatra, can be also used. |
- To create your own PGP key:
Note If you already have a PGP key, you can skip this step. You can use the existing key for the signing process. - Launch the GPA application and go to Keys > New key.
- Enter your full name and the email address from which you are going to send your registration request.
You have now created a PGP key, which you share with the Samsung Developer Center to initiate encrypted communication.
- Launch the GPA application and go to Keys > New key.
- To import the Samsung Developer Center PGP key:
- Go to a PGP key server, such as keyserver.pgp.com.
- Search the keys using the Samsung Developer Center email address (gear2.sec@samsung.com) or the key ID (4D8CE45C).
-
To download the PGP key and save it on your system, click Download.
- Drag and drop the key directly to the GPA application or import it manually by going to Keys > Import Keys.
- Go to a PGP key server, such as keyserver.pgp.com.
- To encrypt your developer certificate request:
- In the GPA application, go to Windows > File Manager.
- Click Open, select the created certificate request file (certificate-request.xml) from the /tizen-wearable-sdk-data/keystore directory, and click OK.
- Click Encrypt, select the Samsung Developer Center key named Gear2 Samsung from the Public Keys list, and click OK.
Note Make sure the hidden attribute of the /tizen-wearable-sdk-data folder is not selected to show it in the GPA File Manager. - Send the encrypted file (certificate-request.xml.gpg) and your public key to the Samsung Developer Center as an email attachment.
In the mail, enter REQUEST FOR SIGNING as subject.
Note PGP is not compatible with the Web mail system. Therefore, if you must encrypt your email message, go to Windows > Clipboard and paste your message in the clipboard window. To encrypt the message, click Encrypt and select the appropriate Samsung Developer Center key from the list. - In the GPA application, go to Windows > File Manager.
- To decrypt your registration file after you receive it from the Samsung Developer Center:
- In the GPA application, go to Windows > File Manager.
- Click Open to find the files to decrypt. Select the file and click Decrypt.
- Enter your password to decrypt the registration file.
- In the GPA application, go to Windows > File Manager.
Registering Certificates
You can register an author certificate using the certificate-registeration.xml file received from the Samsung Developer Center.
To register a certificate:
- On the Tizen IDE for Wearable toolbar, click the
button.
The Register certificates dialog opens.
- Enter the certificate-registeration.xml file path.
- Enter your password.
- Click OK.
The author certificate and distributor certificate files are generated. A default security profile is also created.
| Note |
|---|
|
To install, without the Tizen IDE for Wearable, a wearable application on a wearable device on which no wearable applications have previously been installed:
Adding Certificates to Security ProfileAfter registering, the author and distributor certificates are automatically added to the security profile. To manually change the certificate settings:
Figure: Adding certificates
At least one distributor certificate is required and the default information is filled automatically when a profile is created. Another distributor certificate is optional and is used only for special purposes. In general, you are not required to modify distributor certificates.
|
– Then, click on the Profile, and click “set Active”, you will be prompted to clean all projects, and rebuild. (this last step wasn’t in the documentation)
To check if a WGT file is signed or not, then unzip the wgt file, and open the author-signature.xml file in a text editor, look for the X509Certificate node, and copy and paste it into http://www.sslshopper.com/certificate-decoder.html, you should see something like:
Certificate Information:
Common Name: Open Merchant Account Ltd
Organization: Open Merchant Account Ltd
Locality: Clonmany
State: Donegal
Country: IE
Valid From: October 31, 2012
Valid To: December 31, 2018
Issuer: Tizen Developers CA, Tizen Association
Key Size: 1024 bit
Serial Number: 0142c2e3a0f1
– I.e. the Common name should be your company, not Tizen.
Alternative to sp_send_dbmail
If you’d like to send email from SQL server, but don’t, or can’t setup sp_send_dbmail on your SQL server database, then you can use this CLR stored procedure, which uses Mailgun as an outbound SMTP server.
using System;
using System.Net;
using Microsoft.SqlServer.Server;
using System.Net.Mail;
public partial class StoredProcedures
{
/// <summary>
/// Note: you will need to set
/// EXEC sp_dbcmptlevel ‘GeneralPurpose’, 90
/// ALTER DATABASE GeneralPurpose SET TRUSTWORTHY ON
/// </summary>
/// <param name=”subject”>The subject.</param>
/// <param name=”body”>The body.</param>
/// <param name=”to”>To.</param>
[SqlProcedure]
public static void CLR_SendEmail(string subject, string body, string to)
{
SmtpClient smtpClient = new SmtpClient();
NetworkCredential basicCredential =
new NetworkCredential(“postmaster@xxxx.mailgun.org”, “xxxx”);
MailMessage message = new MailMessage();
MailAddress fromAddress = new MailAddress(“postmaster@xxx.mailgun.org”);smtpClient.Host = “smtp.mailgun.org”;
smtpClient.UseDefaultCredentials = false;
smtpClient.Credentials = basicCredential;message.From = fromAddress;
message.Subject = subject;
//Set IsBodyHtml to true means you can send HTML email.
message.IsBodyHtml = true;
message.Body = body;
message.To.Add(to);try
{
smtpClient.Send(message);
}
catch (Exception ex)
{
//Error, could not send the message
SqlContext.Pipe.Send(ex.Message);
}
SqlContext.Pipe.Send(“Sent” + Environment.NewLine);
}
};
Google Search API with Silverlight and System.Json
There are many ways to handle JSON in .NET, this approach uses a weakly-typed approach, which makes the parsing more flexible to schema changes. I wanted to try the Microsoft approach and use System.JSON – This is all from a .NET 4 environment in Silverlight, with a non-blocking behaviour.
So, from the highest level, this is how I wanted the method to act. – from MainPage.xaml.cs
public MainPage()
{
InitializeComponent();
GoogleSearch.DoSearch(“Hello”, Callback);
}private void Callback(List<GoogleSearchResult> googleSearchResults)
{
// to-do
}
So, in a separate class, I defined a GoogleSearchResult as follows:
public class GoogleSearchResult
{
public string Title;
public Uri Url;
}
Then, to make a HTTP call to the Google custom search API as follows:
public static void DoSearch(string query, Action<List<GoogleSearchResult>> callback)
{
var strUrl = “https://www.googleapis.com/customsearch/v1?”;
strUrl += “q=” + query;
strUrl += “&cx=…”;
strUrl += “&key=…..”;
var wc = new WebClient();
wc.DownloadStringAsync(new Uri(strUrl), callback);
wc.DownloadStringCompleted += DownloadStringCompleted;
}
Then defining the DownloadStringCompleted method as follows:
static void DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
var callback = (Action<List<GoogleSearchResult>>) e.UserState;
var json = JsonValue.Parse(e.Result);
if (json == null || (json[“items”] as JsonArray) == null)
{
callback(null);
return;
}
var lResults = json[“items”].Cast<JsonObject>().Select(jo =>
new GoogleSearchResult
{
Title = jo[“title”],
Url = new Uri(jo[“link”])
}).ToList();
callback(lResults);
}
Notice how the callback function is passed through in the UserState (same as userToken)
Generate static graph images for embedding into emails
The Google Graph API is great, but it’s Javascript based, so therefore unsuitable for embedding into emails, since most, if not all email clients will block the execution of Javascript.
The Google static chart API is an option, but it is officially deprecated, and may not be supported beyond 2015.
Here is an unusual solution, which can be used to generate an image from a web page, and then the resultant image can be embedded into a HTML based email.
First, I took Google’s simple “Pie chart” example, and replaced all the values with variables read from the query string: i.e.
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn(‘string’, getParameterByName(“datatitle”));
data.addColumn(‘number’, getParameterByName(“valuetitle”));
data.addRows(
eval(getParameterByName(“data”))
);var options = {‘title’:getParameterByName(“title”),’width’:”100%”,’height’:”100%”};
var chart = new google.visualization.PieChart(document.getElementById(‘chart_div’));
chart.draw(data, options);
}
Put this online as a web-page, which can be called like this:
Then using a thumbnail generator service, I can create an image from this:
– Which could then be embedded into an email using a simple <img> tag.
Webworks.js – under the hood on port 8472
A relatively recent change to Webworks apps on BB10, was that you had to include the file:
<script src=”local:///chrome/webworks.js” type=”text/javascript”></script> in order to access the native functionality, such as browser invoke etc.
Interestingly, if you enable remote web inspector, you can actually see the contents of this file (listed here), and the underlying “gubbins” are exposed.
What webworks.js is actually doing, is that it converts calls such as blackberry.invoke.invoke({target: “sys.browser”,uri: “xxxx”}); to an AJAX call to localhost on port 8472, which does not appear to be accessible from outside the device itself.
The full protocol is unlikely to be published, and it’s not a good idea to use this protocol directly, it’s more for academic interest.
Here is an example AJAX request
-
Request URL:
-
Request Method:POST
-
Status Code:
200 OK
Send Email from PhantomJS
I was looking for a way to run automated tests on Javascript, and one of the key requirements of automated tests, are that the results are communicated back. As long as I’m just looking for erroneous / exceptional events then email is a great way to get my attention. But I wanted to find an online service that would provide this for me, rather than writing my own server side code, so I tried a few, and came up with mailgun.net
function ObjToQs(obj)
{
str = ”;
for(key in obj) {
str += key + ‘=’ + obj[key] + ‘&’;
}
str = str.slice(0, str.length – 1);
return str;
}var page = require(‘webpage’).create(),
url = ‘https://api.mailgun.net/v2/sandboxed7c45b35fc04752931f87faecae4428.mailgun.org/messages’,
data = {
“from” : “Mailgun Sandbox <postmaster@sandboxed7c45b35fc04752931f87faecae4428.mailgun.org>”,
“to” : “xxxx@gmail.com”,
“subject” : “Hello!”,
“text”: “Test from mailgun / phantomjs”
};page.customHeaders={‘Authorization’: ‘Basic ‘+btoa(‘api:key-xxxxxx’)};
page.open(url, ‘post’, ObjToQs(data), function (status) {
if (status !== ‘success’) {
console.log(‘FAIL to load the log’);
console.log(status);
} else {
console.log(‘Log success’);var result = page.evaluate(function () {
return document.body.innerText;
});console.log(“log Result: ” + result);
phantom.exit();
}
});
I’ve left out my API key, you can get your own at mailgun.net –
A successful result should be as follows:
C:\research\phantomjs>phantomjs errorreport.js
Log success
log Result: {
“message”: “Queued. Thank you.”,
“id”: “<20140422121333.32180.12028@sandboxed7c45b35fc04752931f87faecae4428.mai
lgun.org>”
}
Using Parse.com as a Ajax caching proxy
Plenty of API’s have usage restrictions, either calls per minute, or calls per day etc. But perhaps many of your users search for similar data, and that data remains static. If I’m looking data on the longitude and latitude of a town, then this data is not going to change, then “cloud” caching would be ideal. This solution is not designed for data that may change, i.e. the current weather,
I’ve decided to use Parse.com as the backend, because it has generous free usage limits, (1 milion queries per month), it’s got a Javascript API, and it’s well known, and you can export your data if you ever wanted to move to another system.
So, lets take a simple ajax get request, in the form $.get(url, callback) and write a function with the same signature
function cachedAjaxGet(url,callback)
{
var query = new Parse.Query(AjaxCache);
query.equalTo(“url”, url);
query.first({
success: function(object) {
if (object == undefined)
{
console.log(“cache-miss”);
$.get(url,function(data)
{
var ajaxCache = new AjaxCache();
ajaxCache.save({data: JSON.stringify(data), url: url},
{
success: function(object)
{
console.log(“stored as ” + object.id);
}
});
callback(data);
});
}
else
{
console.log(“cache-hit”);
var result = JSON.parse(object.get(‘data’));
callback(result);
}
}});
}
Then, don’t forget to initialize parse.com as follows
Parse.initialize(“….”, “…”);
var AjaxCache = Parse.Object.extend(“AjaxCache”);
And of course, include the Parse.com library from the CDN:
<script src=”http://www.parsecdn.com/js/parse-1.2.8.min.js”></script>;
Very simple, free phonegap app crash reporting
App crashes are bad. They lead to negative app reviews, and often, the user does not, or cannot describe the exact actions taken just before the app crashed.
There are plenty of good app error reporting tools out there, such as exceptional, and airbrake, but lets say, we just want to have an email whenever a Javascript app crashes on a phonegap app. We want it free, and we want it as simple as possible. – But you’d like a stack trace of the error, and a decent description. – Oh, and let’s do it without requiring server-side code.
So, I set up a free account on FormToEmail.com, pressed the generate code button, and got my user_id and form_id, then I drop this function into my app:
function sendCrashReport(message, url , linenumber, column, errorObj)
{
var stack = “”;
if(errorObj !== undefined) //so it won’t blow up in the rest of the browsers
stack = errorObj.stack;
$.post(‘http://formtoemail.com/user_forms.php’,
{
“user_id” : “……”,
“form_id” : 1,
“message” : message,
“url” : url,
“linenumber” : linenumber,
“stack”: stack
},function(data)
{
console.log(data);
});
}
Then, as close as possible to the initialisation of the page, I write the code:
window.onerror = sendCrashReport;
– Of course, this may not catch compile errors or business logic mess ups, but It’ll catch serious runtime errors that could otherwise crash your app,
AngularJS and BlackBerry 10 Webworks

AngularJS, and in particular, the ionic framework is a great way to develop Javascript apps, with best-practices baked in. It gives y0u two-way data-binding out of the box, and encourages you to separate logic and display, as well as keeping the global namespace clean. – So, I decided to give it a go, and develop an app using the ionic framework, which is based on AngularJS.
So, after getting it up and running on iOS and Android, after a few tweaks, my last platform was BlackBerry, and when firing it up on the simulator, I was disappointed to see that I couldn’t click on any of the links on the list; which was a simple rendering as follows:
<ion-list>
<ion-item ng-repeat=”item in data” type=”item-text-wrap” href=”#/tab/company/{{item.cacheId}}”>
{{item.title}}
</ion-item>
</ion-list>
Nothing special there, and there was no sign of the bug in Chrome, so I couldn’t debug it locally. I needed a way to debug it directly on the device. Then I remembered the remote web inspector. I’d heard of it, but never used it.
Firstly, to enable it, open the browser on the Z10 emulator, and press … => settings => developer tools => web inspector => ON. It shows a IP address, and port, you type this into any webkit browser on the same local network, and then select your application from the list.
When using bbwp to build your bar file, use the -d switch to enable remote web inspector.
You can then see console.log output, and run jquery commands against the UI. I ran the command $(“.item-content”) to see how AngularJS had rendered the list, and I saw the problem immediately. AngularJS had “sanitized” the URL links like so href=”unsafe:local://index.htm#…” which meant that they would be blocked. The solution I found to this, could be improved, but it worked for me:
setTimeout(function () {
console.log(“SearchResultCtrl – Desanitizing… BB10 requirement”);
$( “.item-content” ).each( function( index, element ){
$(this).attr(“href”,$(this).attr(“ng-href”));
});
}, 2000);
And, then when I re-built and deployed the app back on the z10 simulator, it worked like a charm.
In hindsight, perhaps in future, I’ll just wrap my android APKs to run on the BB10 devices, but for the moment, I’m still going to stick with Webworks.
Under the hood InAppBrowser for Cordova 3.5.0 (Phonegap)
In previous versions of Phonegap/Cordova (i.e. 2.x), the InAppBrowser was baked into Cordova.js proper, and was not considered a plugin, it was simply called via “Window.open”, and you got Phonegap’s ‘augmented’ version of the browser control.
However, after upgrading a project to Cordova 3.5.0, the inAppBrowser baffled me, since, although window.open was still working, it wasn’t using the inAppBrowser, so therefore, once window.open was called, the user had left the app, and was then on the web.
Anyway, I finally figured out that you needed to download the InAppBrowser as a plugin. Copy the js files into the src folder (talking about Android here), a couple of images for the forward and back button, and a js file into the www folder.
However that *bloody* js file didn’t work, not sure why, but calls to “require” and “modules”, were simply not there, so, since it was a short file, I decided to pick it apart, and just use the little functionality I required from it.
Now, I’m not advocating this approach, just if you can’t face it any longer, this hack may save you alot of time.
So, instead of Window.open(url, … ), I use a new function AltWindowOpen as follows:
function altWindowOpen(strUrl, strWindowName, strWindowFeatures)
{
console.error(“altWindowOpen()”);
var cb = function(event) {
console.error(“inappBrowser – ” + event.type);
if(event.type == “loadstart”)
{
browserRef_loadstart(event);
}
};
cordova.exec(cb, cb, “InAppBrowser”, “open”, [strUrl, strWindowName, strWindowFeatures]);
}
As you see, I’m only interested in the “loadstart” event, and I want to call browserRef_loadstart() whever that happens. The event object has the property “event.url” so you can see what it’s loaded.
In order to close the browser, you call
cordova.exec(null, null, “InAppBrowser”, “close”, []);
I’ve used console.error instead of console.log so it shows up in logcat more visibly. – Just another trick I discovered tonight.

