Tizen app vibration background

1.6k views Asked by At

I have a Samsung Gear S and I'm bussy writing a web app. I would like to vibrate my app when I get a message from my server. I simply use navigator.vibrate(1000) and this works just fine. But when my app goes to the background the vibration doesn't work anymore. I've found this thread (https://developer.tizen.org/ko/forums/web-application-development/vibration-background?langswitch=ko) in which they face the same problem but there is no solution. Someone also suggested to use alarms to make your app active but I don't know how to do that. I suppose it is something like this:

var alarm = new tizen.AlarmRelative(1);
var service = navigator.vibrate(1000);
tizen.alarm.add(alarm, "org.tizen.browser", service);

This fails because the service isn't correct. How can I get this to work?

5

There are 5 answers

0
Tim On BEST ANSWER

The following method:

You can turn on the screen light first then vibrate.

tizen.power.turnScreenOn();
navigator.vibrate(1000);

doesn't work quite yet. I had to add a delay for the vibration:

tizen.power.turnScreenOn();
setTimeout(function (){
    navigator.vibrate(1000);
}, 500);

EDIT: Also add from the other answers to the config.xml file,

<tizen:setting background-support="enable" background-vibration="enable" />
<tizen:privilege name="http://tizen.org/privilege/power"/>
3
Arup Sarker On

First Method:

You can turn on the screen light first then vibrate.

tizen.power.turnScreenOn();
navigator.vibrate(1000);

It is tricky, but works.

Second Method:

  1. Create a service application which is receive data from server

  2. Create your UI app which need to launch for desired feature.

  3. Make reference in UI app which points to service app

  4. When Service receives data from server, then it will vibrate and lunch the UI app.

In Service app,

var alarm = new tizen.AlarmRelative(10);
var service = new tizen.ApplicationService("http://tizen.org/appsvc/operation/view","http://www.tizen.org");
tizen.alarm.add(alarm, "org.your.app.id", service);
console.log("Alarm added with id: " + alarm.id);
  1. If you need to send data from Service app to UI app, then use message port.
0
Arup Sarker On

You can use Alarm.

var appId = tizen.application.getCurrentApplication().appInfo.id; 
var alarm = new tizen.AlarmRelative(delay);
console.log('Setting relative alarm to ' + delay + ' seconds.');
tizen.alarm.add(alarm, appId);

Add this code fragment when your app receives information from server.

0
Tony On

This works for me.

Find the application.lauch parameter id in your config.xml.

See the example below and the desired privilege and settings.

config.xml:

<tizen:application id="SHrC13kzHD.Alarm" package="SHrC13kzHD" required_version="2.3.2"/>
<tizen:privilege name="http://tizen.org/privilege/power"/>
<tizen:privilege name="http://tizen.org/privilege/internet"/>
<tizen:privilege name="http://tizen.org/privilege/notification"/>
<tizen:privilege name="http://tizen.org/privilege/application.launch"/>
<tizen:setting background-support="enable" encryption="disable" hwkey-event="enable"/>

function multiVibration() {
  tizen.power.turnScreenOn();   
  tizen.application.launch("SHrC13kzHD.Alarm", onsuccess);
  function onsuccess() {
    console.log("Application launched successfully");
  }
  /* Vibrate SOS */
  setTimeout(function (){  navigator.vibrate([100,30,100,30,100,200,200,30,200,30,200,200,100,30,100,30,100]);
    }, 500);
}

//test
multiVibration();
0
motu On

I think background vibration is "not official" supported in web-apps, but you can activate it. Just add following key to your config.xml:

<tizen:setting background-support="enable" background-vibration="enable" />

This will allow you to vibrate even if the screen is off. (See also page 12 in tizen-2.3-wrt-core-spec.pdf)

So far this should work, but I think you can't upload an app with this setting to the Tizen-store...

[EDIT]

Today I played a bit with the vibration and just wanted to add my discoveries. If you dont use the 'background-vibration="enable" ' key it seems you have two options, but both are more like a workaround:

  1. Just use notifications (Notification) This will push a Notification to the notification area of the watch including a option to vibrate
  2. The other way with the alarm is the other way, but it will need a bit more than just an alarm.

Your app need some conditions to be able to vibrate from background:

  • the screen needs to be on
  • your app needs to be in foreground

So for the second way you need to do a bit more stuff. I created a new project with the wizard (TAU basic) and midified the app.js as followed:

var myAlarm = null;
var page = document.querySelector('#main');
var remoteMsgPort = null;

( function () {
    window.addEventListener( 'tizenhwkey', function( ev ) {
  if( ev.keyName === "back" ) {
   var page = document.getElementsByClassName( 'ui-page-active' )[0],
    pageid = page ? page.id : "";
   if( pageid === "main" ) {
    try {
     // cleanup 
     showAfterWakeup(false);
     tizen.power.unsetScreenStateChangeListener();
     tizen.application.getCurrentApplication().exit();
    } catch (ignore) {
    }
   } else {
    window.history.back();
   }
  }
 } );

 /**
  * Method to set the app as topmost app. This causes the app to be shown
  * after display turns on, instead of the clock face.
  * 
  * @param {boolena}enable
  *            True to enable, false to disable
  */
 function showAfterWakeup(enable) {
  var param = [{
   key: "state",
   value: enable ? "show" : "hide"
  }];
  
  if(remoteMsgPort !== null) {
   remoteMsgPort.sendMessage(param);
   console.debug("remoteMsgPort.sendMessage(" + JSON.stringify(param) + ")");
  }
 }
 
 function checkLaunchRequest() {
  var appControl,
   appOperation,
   ret = false;
  
  try {
   appControl = tizen.application.getCurrentApplication().getRequestedAppControl().appControl;
   appOperation = appControl.operation;
   console.debug("checkLaunchRequest operation: " + appOperation);
   
   // check if operation view was used, as we set this for the alarm
   if (appOperation.indexOf('http://tizen.org/appcontrol/operation/view') !== -1) {
    console.debug("URI: " + JSON.stringify(appControl.uri));
    // set as topmost app to be in foreground when screen turns on
    showAfterWakeup(true);
    // turn the screen on
    tizen.power.turnScreenOn();
    ret = true;
   }
  } catch (err) {
   console.error("checkLaunchRequest Invalid launch request: " + err);
  }
 }
 
 function onScreenStateChanged(previousState, changedState) {
  console.log("Screen state changed from " + previousState + " to " + changedState);
  
  if(previousState === "SCREEN_OFF" && changedState !== "SCREEN_OFF" ){
   console.log("screen changed to ON");
   navigator.vibrate([250,100,350]);
   showAfterWakeup(false);
  }else if(previousState !== "SCREEN_OFF" && changedState === "SCREEN_OFF" ){
   // Triggers an alarm on a given date/time --> 10sec from now
   var date = new Date();
   date.setSeconds(date.getSeconds() + 10);
   
   // check if already a alarm was set and remove it to avoid multiple alarms
   if(myAlarm !== null){
    tizen.alarm.remove(myAlarm);
    myAlarm = null;
   }
   
   myAlarm = new tizen.AlarmAbsolute(date);
   var appControl = new tizen.ApplicationControl("http://tizen.org/appcontrol/operation/view");
   tizen.alarm.add(myAlarm, tizen.application.getCurrentApplication().appInfo.id, appControl);
   console.log("Alarm added set for: " + date.toLocaleTimeString() + " with id: " + myAlarm.id);
   
  }
 }
 
 /**
  * Callback for pageshow event
  */
 function onPageShow(){
  console.log("pageshow");

  /*
   * check if alarm called app
   * if false we interpret as the first app start, not clean but will do it for demo ;)
   */
  if(checkLaunchRequest() !== true){
   // just for testing vibration
   var text = document.querySelector('.ui-listview');
   text.addEventListener('click', function(ev) {
    console.log("clicked: " + ev.target.nodeName);
    navigator.vibrate(500);
   });
  }
 }

 /**
  * init view
  */
 function init(){
  try {
   remoteMsgPort = tizen.messageport.requestRemoteMessagePort('starter', 'Home.Reserved.Display');
  } catch (err) {
   console.error("Exception for requestRemoteMessagePort: " + err);
  }
  showAfterWakeup(false);
  page.addEventListener('pageshow', onPageShow);

  // Sets the screen state change listener.
  tizen.power.setScreenStateChangeListener(onScreenStateChanged);
 }
 
 window.onload = init();
} () );

So what is done here:

  1. in the onload event we register a remote message port (MessagePort) and add some event listener for "page show" and change of screen states.
  2. After app is started we wait till app goes to background and screen turns off
  3. In onScreenStateChanged we get that the screen turned off and we add a new alarm which will be triggered in 10sec.
  4. The alarm triggers the app and the pageShow event so that checkLaunchRequest will be called.
  5. The app control operation is .../view so the app is set as top most app and the screen is turned on
  6. Now we are again in the onScreenStateChanged, but this time see that the screen was turned on and do vibrate

I know this seems to be overloaded to just vibrate, but I think this is the only way to get the vibration 100% to work after the screens was turned off. In https://www.w3.org/TR/2014/WD-vibration-20140211/ they descripe that if the app is not visible it should not vibrate, so I think this is why the screens needs to be on and the app needs to be in foreground. Somehow it seems logical to me that an app can't vibrate if it is in background...

I hope this helps ;)