Introduction
The tutorial found below teaches developers how to build a basic sample application for Samsung Accessory Protocol (SAP). This is a three-part series. It also teaches how to test the applications using the Emulator. Part 1 is all about the development on the Android side. Part 2 deals with the development on the Tizen side. Part 3 is about the complete application for SAP, which is basically the packaging of the Android part and the Tizen part.
Development on the Android Side
Development on the Tizen Side
We will now proceed to the Tizen development part of the application for SAP. If you haven't created your Android part of your application, please refer to the above video.
Let's begin. First let's open the Tizen IDE for Wearable and select a workspace.
Go ahead and close the tip of the day.
And let's create a new project. Select File -> New -> and Tizen Wearable Web Project.
Select Template, Basic, and I will name this one "SimpleSAPConsumer" which is an alternative to the android application sample SAP provider. This will be the one to receive the communication from the android side.
Now that we have a project we can work with, first let's modify the interface in index.html and make sure the title is "SAP Consumer."
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
<meta name="description" content="Tizen Wearable basic template generated by Samsung Wearable Web IDE"/>
<title>SAP Consumer</title>
<link rel="stylesheet" type="text/css" href="css/style.css"/>
<script src="js/main.js"></script>
</head>
And put this in the UI slot:
<div class="ui-title">SAP CONSUMER</div>
<div>
<input type=button value="Connect" onclick="connect();" style="width: 32%; height: 60px; -webkit-tap-highlight-color: rgba(0,0,0,0);"/>
<input type=button value="Fetch" onclick="fetch();" style="width: 32%; height: 60px; -webkit-tap-highlight-color: rgba(0,0,0,0);"/>
<input type=button value="Disconnect" onclick="disconnect();" style="width: 32%; height: 60px; -webkit-tap-highlight-color: rgba(0,0,0,0);"/>
</div>
<div id="resultBoard">
<!---->
</div>
So we have a title that says SAP Consumer, with three buttons: Connect
, Fetch
, and Disconnect
that each have a function, and the last values are for styles of the button, while <div id="resultBoard">
will display all the communication messages received from the android device.
Next let's add the script functionality, so open main.js. Let's add four variables. The first variable is the SAAgent
, this will be mirroring the SAAgent
in the android side. Let's initialize it to null. And a variable for the SASocket
, also mirroring the android side, also intialized to null. And a CHANNELID
. Make sure to initialze this to the CHANNELID
same as the android side. And the ProviderAppName
, the name of your Provider Application is the name of the android side application, so for us it's "SimpleSAPProvider."
var SAAgent = null;
var SASocket = null;
var CHANNELID = 123;
var tag = "SIMPLE SAP ";
var ProviderAppName = "SimpleSAPProvider";
Next, let's add a content writer. So basically this function createHTML
accepts a parameter (log_string
) and writes it on the resultBoard
referenced to the index.html
object, and adds logs there.
function createHTML(log_string)
{
var log = document.getElementById('resultBoard');
log.innerHTML = log.innerHTML + "<br> : " + log_string;
}
Next let's add another function, and this function is for error logging, as you can see, it logs errors on the console and your IDE.
function onerror(err) {
console.log("ONERROR: err [" + err.name + "] msg[" + err.message + "]");
}
Let's add a variable for the agentCallback
. Basically what this does is that it is responsible for connection to the android side and alerts you that connection has been established.
var agentCallback = {
onconnect : function(socket) {
console.log( "agentCallback onconnect" + socket);
SASocket = socket;
alert("SAP Connection established with RemotePeer");
createHTML("startConnection");
SASocket.setSocketStatusListener(function(reason){
console.log("Service connection lost, Reason : [" + reason + "]");
disconnect();
});
},
onerror : onerror
};
Let's add another variable for the AgentFindCallback
. So what this one does is that it locates the peer
using the Samsung Accessory Protocol that have a certain provider app name.
var peerAgentFindCallback = {
onpeeragentfound : function(peerAgent) {
try {
if (peerAgent.appName == ProviderAppName) {
console.log(" peerAgentFindCallback::onpeeragentfound " + peerAgent.appname + " || " + ProviderAppName);
SAAgent.setServiceConnectionListener(agentCallback);
SAAgent.requestServiceConnection(peerAgent);
} else {
console.log(" peerAgentFindCallback::onpeeragentfound else");
alert("Not expected app!! : " + peerAgent.appName);
}
} catch(err) {
console.log(" peerAgentFindCallback::onpeeragentfound exception [" + err.name + "] msg[" + err.message + "]");
}
},
onerror : onerror
}
Let's add another function named onsuccess
to handle the success response of connection from the agent and peer. This is the alternative to the onerror
.
function onsuccess(agents) {
try {
if (agents.length > 0) {
SAAgent = agents[0];
SAAgent.setPeerAgentFindListener(peerAgentFindCallback);
SAAgent.findPeerAgents();
console.log(" onsuccess " + SAAgent.name);
} else {
alert("Not found SAAgent!!");
console.log(" onsuccess else");
}
} catch(err) {
console.log("onsuccess exception [" + err.name + "] msg[" + err.message + "]");
}
}
Now let's add another function to write the result to our HTML board, onreceive
that accepts a channelId
and data. This function will be calling the createHTML
function, which logs in the data received. This one mirrors the onreceive
function from the android side application.
function onreceive(channelId, data) {
createHTML(data);
}
Now let's add the button methods. First, connect()
. So as you can see, the if statement checks if the SASocket
is already connected. If it is, an alert shows that indicates it is already connected. If not, we use the webapies
to request a connection from the SAAgent
that returns a success or an error. In addition, there is a log to catch the errors.
function connect() {
if (SASocket) {
alert('Already connected!');
return false;
}
try {
webapis.sa.requestSAAgent(onsuccess, onerror);
} catch(err) {
console.log("exception [" + err.name + "] msg[" + err.message + "]");
}
}
Next is the fetch()
method, which gets the data from the android side. We send the data to the android side CHANNELID
which is defined, and an empty string.
function fetch() {
try {
SASocket.setDataReceiveListener(onreceive);
SASocket.sendData(CHANNELID, "");
} catch(err) {
console.log("exception [" + err.name + "] msg[" + err.message + "]");
}
Finally, the last button function is disconnect()
, to proactively disconnect your wearable and your android device. So in this first if
statement, we check if the SASocket
is not null, console logs DISCONNECT SASOCKET NOT NULL
(of course) and proactively sends a close (SASocket.close();
) to the connection, else there's an error.
function disconnect() {
try {
if (SASocket != null) {
console.log(" DISCONNECT SASOCKET NOT NULL");
SASocket.close();
SASocket = null;
createHTML("closeConnection");
}
} catch(err) {
console.log(" DISCONNECT ERROR: exception [" + err.name + "] msg[" + err.message + "]");
}
}
And the last thing we have to add is a script for us to be able to close the application, with a reference to the close function of the tizenhwkey
.
}
window.onload = function () {
document.addEventListener('tizenhwkey', function(e) {
if(e.keyName == "back")
tizen.application.getCurrentApplication().exit();
});
};
If you want to add some styles to your application, go to style.css. So, for example, you can change the background-color
color to white, or you can add a style rule for the title. In this case, our title will be blue, with a font size of 24px, while the rest is for spacing.
body {
margin: 0px auto;
background-color:white;
}
.ui-title {
color: blue;
font-size: 24px;
white-space: nowrap;
margin: 0px;
padding-left: 16px;
padding-right: 16px;
}
Similar to the android side we will be needing metadata for Tizen as well. Think of this as the common ground where the two technologies meet. In the project folder, right-click and add a folder named res. Inside res, add another folder named xml. As you can see this is similar to the android side.
We'll also be adding an XML file inside.
Recall the name of the XML file that you named your android side, so for me it's sapservices.xml. It's OK if it initially says it is an unsupported file, we will be modifying this. Now that we have the metadata XML file in place all we have to do is put contents into it.
<resources>
<application name="SimpleSAPConsumer">
<serviceProfile
role="consumer"
name="sapimageswitcher"
serviceTimeout="10"
serviceLimit="ANY"
version="2.0"
id="/system/sapimageswitcher">
<supportedTransports>
<transport type="TRANSPORT_WIFI"/>
</supportedTransports>
<serviceChannel
id="123"
reliability="enable"
priority="low"
dataRate="low"/>
</serviceProfile>
</application>
</resources>
Now we have a working metadata in our side. What's left is the modification of our config.xml file. Make sure there is a reference to the metadata we created. In this case, AccessoryServiceLocation
. Also ensure there is a privilege for our widget to be able to use the accessoryprotocol. Now the config file is set up for SAP use, and that's about it for coding.
="1.0" ="UTF-8"
<widget viewmodes="maximized" version="1.0.0" id="http://yourdomain/SimpleSAPConsumer" xmlns:tizen="http://tizen.org/ns/widgets" xmlns="http://www.w3.org/ns/widgets">
<tizen:application id="HUbSOmFAGb.SimpleSAPConsumer" required_version="2.2" package="HUbSOmFAGb"/>
<content src="index.html"/>
<feature name="http://tizen.org/feature/screen.size.all"/>
<icon src="icon.png"/>
<tizen:metadata value="res/xml/sapservices.xml" key="AccessoryServicesLocation"/>
<name>SimpleSAPConsumer</name>
<tizen:privilege name="http://developer.samsung.com/privilege/accessoryprotocol"/>
</widget>
Now that we have everything in place let's just build the project. So click Project -> Build Project.
This will produce a .wgt file. This is the file we will need to attach it to the android side.
Packaging the Integrated Application
Now we will be integrating android and Tizen, as well as testing our application.
Let's begin. Now that we have our applications with both android and Tizen parts, we will start by packaging the application together. In your Tizen application, there will be a file with a .wgt file extension. Simply copy it and paste it in your android application assets folder. The reason for this is the application we develop is an integrated type application which means that the application will simultaneously be installed to the Galaxy Gear device upon installing the SAP service to the android device.
We now have a packaged application. Let's try it out. Testing the application on the actual Galaxy Gear device, paired with an android device, you only need to run the application on the android device, and the rest will be done by the Gear Manager application. The Gear Manager application is what we use pair Galaxy Gear devices with the Samsung Android smartphone, and can be downloaded from the Samsung App Store. You can only test applications you've created on actual Galaxy Gear devices if you have a certificate registered with your on Galaxy Gear DUID.
If you don't have a certificate with an actual device DUID, don't worry, you can register a certificate with an emulator's DUID to be able to test your applications by emulating the SAP pairing over USB. If your device has Gear Manager installed, uninstall it, as well as the related applications for Gear Manager.
To prepare testing over USB we will need to first install three APKs from the downloaded file name, Applications for Emulator. This can be downloaded from http://developer.samsung.com/samsung-gear. Install it in this order:
- SAccessoryService_Emul.apk
- SAFTCore_Emul.apk
- HostManagerForEmul.apk
Now that you have installed them, notice that only the last APK has a UI. This is the test if the device is connected to the emulated SAP environment over USB. Next, let's establish the connection. Make sure only one android device is connected via USB. Make sure that you have the path to where you can call the android debug bridge. You also need to have the Tizen IDE for Wearable. Make sure this is up and running.
Open a window for terminal and go to where your adb is. If you have not defined it in the environment path, key in:
adb -d forward tcp:8230 tcp:8230
This will make sure that the SAP communication is forwarded to your android device.
Run HostManagerForEmul in your android device. This should say "Disconnected" for now. Start an emulated wearable device in your Tizen IDE and wait for it to fully boot up.
The text displayed in the android device should now say "Connected."
If that doesn't work, right-click on the emulator, click on "Shell," and key in:
killall sap-server
This should stop the service in the emulator.
Now that we have a connection first run the android application and this should start the service on the android device.
Then go to your Tizen IDE and run the Wearable Application. And we should have this in place:
So now you can test the application. Go ahead and click Connect, which should then connect to your actual android device. Then click OK to dismiss the alert. Then click Fetch to get the manufacturer, the model from the phone, as well as the minutes and the seconds time. You can click "Disconnect" if you want to stop it. You can take note of the console for logs for debugging purposes.