I'm developing a NativeScript application which will make use of listening to the call state of the phone. For this i'm using CXCallObserver and CXCallObserverDelegate which I set up as following:
module.exports = {
phoneDelegate: NSObject.extend({
initWithResolveReject: function(resolve, reject){
var self = this.super.init();
if(self){
this.resolve = resolve;
this.reject = reject;
}
return self;
},
callObserverCallChanged: function(observer, call){
console.log("This log is not triggering");
if(call.hasEnded){
// call has ended
this.resolve({phoneState: "ended"});
}
if(call.isOutgoing && !call.hasConnected){
// Dialing out
this.resolve({phoneState: "outgoing call"});
}
if(!call.isOutgoing && !call.hasConnected && !call.hasEnded){
// Call is incoming
this.resolve({phoneState: "incoming call"});
}
if(call.hasConnected && !call.hasEnded){
// Call is ongoing
this.resolve({phoneState: "ongoing call"});
}
}
}, {
protocols: [CXCallObserverDelegate]
}),
registerListener: function(){
return new Promise((resolve, reject) => {
try{
this.callObserver = new CXCallObserver();
let myCallDelegate = this.phoneDelegate.alloc().initWithResolveReject(resolve, reject);
this.callObserver.setDelegateQueue(myCallDelegate, null);
console.log("phone listener registered");
} catch(error) {
reject({error: error});
}
})
}
}
The listener is getting registered as it should, at least no errors are thrown and the last console log in "registerListener" is executed as it should.
When I try to make a phone call, either incoming or outgoing nothing happens. At least the first console log in "callObserverCallChanged" should execute on any phone state change. But nothing happens.
Any one got any suggestion what might be wrong?
let myCallDelegate =
this.phoneDelegate.alloc().initWithResolveReject(resolve, reject);
this.callObserver.setDelegateQueue(myCallDelegate, null);
Ok the solution was quite embarrassing. The myCallDelegate instance was destroyed before doing anything due to not assigning it to the class. Well here is the solution:
this.myCallDelegate = this.phoneDelegate.alloc().initWithResolveReject(resolve, reject);
this.callObserver.setDelegateQueue(this.myCallDelegate, null);
Shoutout to tsonevn for taking his time and finding this misstake.
Related
is there anything like onCancel for a StreamSubscription?
example:
var subscription = someStream.listen((item) => null);
subscription.cancel(); // does this trigger any event?
I ended up creating a _StreamSubscriptionDelegate that delegates all methods and so I can put some logic when the subscription is cancelled, however, maybe there is an easier solution to it.
If the stream comes from a StreamController, then the controller is notified of the cancel. The listener is expected to keep track of their own subscription, so if one part of the client code needs to know that another part has cancelled the stream, then wrapping the subscription in something which records that you cancelled it, is a perfectly good approach.
Another approach could be to wrap the stream before listening to it:
Stream<T> onCancel<T>(Stream<T> source, void onCancel()) async* {
bool isCancelled = true;
try {
await for (var event in source) {
yield event; // exits if cancelled.
}
isCancelled = false;
} finally {
if (isCancelled) onCancel();
}
}
or
Stream<T> onCancel<T>(Stream<T> source, void onCancel()) {
var sink = StreamController<T>();
sink.onListen = () {
var subscription = source.listen(sink.add, onError: sink.onError, onDone: sink.close);
sink
..onPause = subscription.pause
..onResume = subscription.resume
..onCancel = () {
subscription.cancel();
onCancel();
};
};
return sink.stream;
}
I have the following code for my IOS implementation, the problem is that the WroteCharacteristicValue event is never fired. Is is being fired on the android side when I connect to the same module. Any ideas what to do?
public void StartUpdates ()
{
// TODO: should be bool RequestValue? compare iOS API for commonality
bool successful = false;
if(CanRead) {
Console.WriteLine ("** Characteristic.RequestValue, PropertyType = Read, requesting read");
_parentDevice.UpdatedCharacterteristicValue += UpdatedRead;
_parentDevice.ReadValue (_nativeCharacteristic);
successful = true;
}
if (CanUpdate) {
Console.WriteLine ("** Characteristic.RequestValue, PropertyType = Notify, requesting updates");
_parentDevice.UpdatedCharacterteristicValue += UpdatedNotify;
_parentDevice.WroteCharacteristicValue += Wrote; // -DP here??
_parentDevice.SetNotifyValue (true, _nativeCharacteristic);
successful = true;
}
Console.WriteLine ("** RequestValue, Succesful: " + successful.ToString());
}
void Wrote(object sender, CBCharacteristicEventArgs e) {
System.Diagnostics.Debug.WriteLine("Characteristic Write Complete!");
this.WriteComplete (this, new CharacteristicReadEventArgs () {
Characteristic = new Characteristic(e.Characteristic, _parentDevice)
});
}
The WroteCharacteristic will only fire if the characteristic writes with response.
You can check it with:
var prop = _nativeCharacteristic.Properties;
if(prop.HasFlag(CBCharacteristicProperties.Write))
{
// Event can be used
}
else if(prop.HasFlag(CBCharacteristicProperties.WriteWithoutResponse))
{
// Event will not fire if WriteWithoutResponse
}
Btw: we provide a plugin for BLE, so you don't have to care about platform sepcific stuff ;) http://smstuebe.de/2016/05/13/blev1.0/
I'm trying make a firefox add-on, which reloads a page automatically under some conditions.
First I add a contentScript to a tab to get some information on the page in my addon
tab.attach({
contentScript:self.port.emit...
I have it working to the point of the refresh with
tab.reload();
but then an alert pops up every time "if it should resend data".
I want to resend the data automatically.
How and where do I do it? In the add-on or in the contentScript?
Has it to do with the Load Flags constant?
This clicks the accept button when the prompt opens. But you see the prompt window for like a couple hundred ms.
i had to use setTimeout with 0 wait time other wise the aDOMWindow.args property and aDOMWindow.Dialog and a bunch of other stuff would be undefined or null so weird. But this works:
var stringBundle = Services.strings.createBundle('chrome://browser/locale/appstrings.properties');
try {
windowListener.unregister();
} catch (ignore) {}
var windowListener = {
//DO NOT EDIT HERE
onOpenWindow: function(aXULWindow) {
// Wait for the window to finish loading
let aDOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
aDOMWindow.addEventListener('load', function() {
aDOMWindow.removeEventListener('load', arguments.callee, false);
windowListener.loadIntoWindow(aDOMWindow, aXULWindow);
}, false);
},
onCloseWindow: function(aXULWindow) {},
onWindowTitleChange: function(aXULWindow, aNewTitle) {},
register: function() {
// Load into any existing windows
let XULWindows = Services.wm.getXULWindowEnumerator(null);
while (XULWindows.hasMoreElements()) {
let aXULWindow = XULWindows.getNext();
let aDOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
windowListener.loadIntoWindow(aDOMWindow, aXULWindow);
}
// Listen to new windows
Services.wm.addListener(windowListener);
},
unregister: function() {
// Unload from any existing windows
let XULWindows = Services.wm.getXULWindowEnumerator(null);
while (XULWindows.hasMoreElements()) {
let aXULWindow = XULWindows.getNext();
let aDOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
windowListener.unloadFromWindow(aDOMWindow, aXULWindow);
}
//Stop listening so future added windows dont get this attached
Services.wm.removeListener(windowListener);
},
//END - DO NOT EDIT HERE
loadIntoWindow: function(aDOMWindow, aXULWindow) {
if (!aDOMWindow) {
return;
}
if (aDOMWindow.location == 'chrome://global/content/commonDialog.xul') {
var repostString = stringBundle.GetStringFromName('confirmRepostPrompt');
var repostStringFormatted = stringBundle.formatStringFromName('confirmRepostPrompt', [aDOMWindow.Application.name], 1);
aDOMWindow.setTimeout(function() {
console.log('setimeout val 00:', aDOMWindow.args)
//aDOMWindow.args and aDOMWindow.Dialog is not available till after setTimeout of 0 so weird
if (aDOMWindow.args.text == repostString || aDOMWindow.args.text == repostStringFormatted) {
console.log('this is resend prompt so accept it');
//aDOMWindow.Dialog.ui.button0.click(); //doesnt work
//aDOMWindow.Dialog.onButton0(); // doesnt work
//aDOMWindow.ondialogaccept(); //doesnt work
var dialog = aDOMWindow.document.getElementById('commonDialog');
var btnAccept = aDOMWindow.document.getAnonymousElementByAttribute(dialog, 'dlgtype', 'accept');
btnAccept.click();
console.log('clicked');
}
}, 0);
}
},
unloadFromWindow: function(aDOMWindow, aXULWindow) {
if (!aDOMWindow) {
return;
}
}
};
windowListener.register();
open scratchpad. set environemnt to browser. run the code. refresh a page to get prompt you'll see it get clicked.
I'm able to create a XMPP connection on page load. However whenever I move to another pages, I want to use the same connection to remove recurring notifications in client. I've used following code.
$(document).bind('connect', function (ev, data) {
var jid = $.jStorage.get('JID', null);
var sid = $.jStorage.get('SID', null);
var rid = $.jStorage.get('RID', null);
if ((jid != null) && (sid != null) && (rid != null)) {
var conn = new Strophe.Connection("http://localhost:5280/xmpp-httpbind");
conn.attach(jid, sid, rid, function () {
alert('Connection attach success.');
Gab.connection = conn;
});
}
else {
var conn = new Strophe.Connection("http://localhost:5280/xmpp-httpbind");
conn.connect(data.jid, data.password, function (status) {
if (status === Strophe.Status.CONNECTED) {
$(document).trigger('connected');
} else if (status === Strophe.Status.DISCONNECTED) {
$(document).trigger('disconnected');
}
});
Gab.connection = conn;
}
});
And in unload:
$(window).unload(function () {
if (Gab.connection != null) {
Gab.connection.pause();
$.jStorage.set('JID', Gab.connection.jid);
$.jStorage.set('SID', Gab.connection.sid);
$.jStorage.set('RID', Gab.connection.rid);
} else {
$.jStorage.flush();
}
// Gab.connection = null;
alert('paused/disconnected');
})
It attaches to connection, however as soon as it attaches, it says (POST http://localhost:5280/xmpp-httpbind 404 Not Found 36ms) in Firebug console. Any ideas?
Thanks in advance.
You should not trust unload. Instead store/update your RID on every cb from the xmpp server. Make sure your RID is getting incremented on each call as well.
Make sure to inspect the body of the message. Some XMPP servers return HTTP 404 on terminate.
I want to open the link when the user uninstalls the addon, so for this what i have to code and under which event.
If anybody know about this then please help me out.
Currently this is what I am doing at the time of uninstall. But gBrowser.addTab(Website + 'uninstalled=true&token=' + uniqueguid); is not working over here.
var UninstallObserver = {
_uninstall : false,
observe : function(subject, topic, data) {
//===Write Code here for Delete File Uninsatll Time
//alert("Uninstall Time Delete File");
var Filename = "webmail";
// Delete all template file.
try{
var pref = Components.classes["#mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
var finished = "";
pref.setBoolPref("myextension.install.just_installed", false);
}
catch(e) {}
gBrowser.addTab(Website + 'uninstalled=true&token=' + uniqueguid);
var file = Components.classes["#mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
file.initWithPath(Components.classes["#mozilla.org/file/directory_service;1"].getService( Components.interfaces.nsIProperties).get("ProfD", Components.interfaces.nsIFile).path+"\\DefaultTemplate.txt");
if ( file.exists() == true )
{
var aFile = Components.classes["#mozilla.org/file/local;1"].createInstance();
if (aFile instanceof Components.interfaces.nsILocalFile)
{
aFile.initWithPath(Components.classes["#mozilla.org/file/directory_service;1"].getService( Components.interfaces.nsIProperties).get("ProfD", Components.interfaces.nsIFile).path + "\\DefaultTemplate.txt");
aFile.remove(false);
}
}
//=======
if (topic == "em-action-requested") {
subject.QueryInterface(Components.interfaces.nsIUpdateItem);
if (subject.id == MY_EXTENSION_UUID)
{
if (data == "item-uninstalled")
{
//==Delete File Whenever Uninstall
//alert("When Uninatall");
//===========
data = "item-cancel-action";
this._uninstall = true;
}
if (data == "disabled")
{
// alert("You are not allow to disable SysLocker.");
this._uninstall = true;
}
else if (data == "item-cancel-action")
{
this._uninstall = false;
}
}
}
else if (topic == "quit-application-granted")
{
data = "item-cancel-action";
if (this._uninstall)
{
//Code here to delete registry
}
this.unregister();
}
},
register : function() {
var observerService =
Components.classes["#mozilla.org/observer-service;1"].
getService(Components.interfaces.nsIObserverService);
observerService.addObserver(this, "em-action-requested", false);
observerService.addObserver(this, "quit-application-granted", false);
},
unregister : function() {
var observerService =
Components.classes["#mozilla.org/observer-service;1"].
getService(Components.interfaces.nsIObserverService);
observerService.removeObserver(this,"em-action-requested");
observerService.removeObserver(this,"quit-application-granted");
}
}
Thanks
0) What kind of extension is this? I assume it's a regular extension requiring restart; bootstrapped (restartless) extensions have their own uninstall notification.
1) Per the MDC docs, the em-action-requested notification was replaced with a different notification in Firefox 4+, are you testing with Firefox 4 or 3.6?
2) How exactly is gBrowser.addTab "not working over here"? Does the code get to that point? Do you get any messages in the Error Console (see that page for set up tips)? If you put your code in an XPCOM component (which is correct), you'll first have to get a reference to a browser window. See Working with windows in chrome code.
I don't think that the em-action-requested topic is posted to observers until the extension is actually uninstalled, which happens on restart (assuming it is not a restartless extension). When are you expecting the new tab to appear? I would try setting a pref when the uninstall topic is triggered and checking for that pref on startup. If it is there, you can display your tab and remove the pref.