Im pretty much new in sip development and trying to implement a windows phone 8 client using pjsip.
ive build the sample application from pjsip ,which creates pjsua app with telnet connectivity.
Right now ,what i dont get is,how will i use this library and integrate in my app without telnet,
i just need to put a manual dial pad and call from there,to accomplish this,what is going to be the procedure?
pjsip for android or iphone has two sample application ,csipsimple and siphon ,but pjsip for windows phone 8 has no application like this.
any help regarding the way to go ahead would be very helpful.
Thanks
Since you mention that you've tried the windows phone telnet app sample, I assume you've downloaded the PJSIP winphone source as mentioned in their wp8 getting started guide. To create a simple app that perform outgoing and receive incoming call as you mentioned, you can simply reuse this winphone project.
Open the winphone project and do:
Create new Windows Phone project and set this as startup project (let's call this project SIP_UI). This will serve as the UI. You can just create a "Call button" that will perform outgoing call later.
Follow the existing pjsua_wp WMAppManifest.xml settings for this SIP_UI. Especially the capabilities part. Your app won't work if you simply use the default settings.
Create new Windows Phone Runtime project (let's call this SIP_WINPRT). Create a class and a method inside of this class that will perform the actual call later.
Change property setting for SIP_WINPRT (right click SIP_WINPRT project -> property) by following the existing pjsua_wp_backend's. Change especially on the References, Additional include directories, and preprocessor definitions. Adjust the path accordingly.
Search for simple_pjsua.c in the winphone sample. And try to implement that in the class you've created in SIP_WINPRT. Sample that I've created:
#include "pch.h"
#include "backend.h"
#include "pjsua.h"
#define SIP_DOMAIN "dogdomain"
#define SIP_USER "dog"
#define SIP_PASSWD "dog"
using namespace backend;
using namespace Platform;
SipletRuntimeComponent::SipletRuntimeComponent()
{
}
/* Display error and exit application */
static void error_exit(const char *title, pj_status_t status)
{
//pjsua_perror(THIS_FILE, title, status);
pjsua_destroy();
exit(1);
}
/* Callback called by the library upon receiving incoming call */
static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id,
pjsip_rx_data *rdata)
{
pjsua_call_info ci;
PJ_UNUSED_ARG(acc_id);
PJ_UNUSED_ARG(rdata);
pjsua_call_get_info(call_id, &ci);
//PJ_LOG(3,(THIS_FILE, "Incoming call from %.*s!!",
// (int)ci.remote_info.slen,
// ci.remote_info.ptr));
/* Automatically answer incoming calls with 200/OK */
pjsua_call_answer(call_id, 200, NULL, NULL);
}
/* Callback called by the library when call's media state has changed */
static void on_call_media_state(pjsua_call_id call_id)
{
pjsua_call_info ci;
pjsua_call_get_info(call_id, &ci);
if (ci.media_status == PJSUA_CALL_MEDIA_ACTIVE) {
// When media is active, connect call to sound device.
pjsua_conf_connect(ci.conf_slot, 0);
pjsua_conf_connect(0, ci.conf_slot);
}
}
/* Callback called by the library when call's state has changed */
static void on_call_state(pjsua_call_id call_id, pjsip_event *e)
{
pjsua_call_info ci;
PJ_UNUSED_ARG(e);
pjsua_call_get_info(call_id, &ci);
//PJ_LOG(3,(THIS_FILE, "Call %d state=%.*s", call_id,
// (int)ci.state_text.slen,
// ci.state_text.ptr));
}
int SipletRuntimeComponent::SipCall(int address)
{
/* Create pjsua */
pj_status_t status;
status = pjsua_create();
if (status != PJ_SUCCESS){
//Error in pjsua_create()
return -1;
}
/* Validate the URL*/
char url[50] = "sip:cat:cat#catdomain:5060";
status = pjsua_verify_url(url);
if (status != PJ_SUCCESS){
//Invalid URL given
return -1;
}
/* Init pjsua */
{
pjsua_config cfg;
pjsua_logging_config log_cfg;
pjsua_config_default(&cfg);
cfg.cb.on_incoming_call = &on_incoming_call;
cfg.cb.on_call_media_state = &on_call_media_state;
cfg.cb.on_call_state = &on_call_state;
pjsua_logging_config_default(&log_cfg);
log_cfg.console_level = 4;
status = pjsua_init(&cfg, &log_cfg, NULL);
if (status != PJ_SUCCESS){
//Error in pjsua_init()
pjsua_destroy();
return -1;
}
}
/* Add UDP transport. */
{
pjsua_transport_config cfg;
pjsua_transport_config_default(&cfg);
cfg.port = 5060;
status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &cfg, NULL);
if (status != PJ_SUCCESS){
//Error creating transport
pjsua_destroy();
return -1;
}
}
/* Initialization is done, now start pjsua */
status = pjsua_start();
if (status != PJ_SUCCESS){
//Error starting pjsua
pjsua_destroy();
return -1;
}
/* Register to SIP server by creating SIP account. */
pjsua_acc_id acc_id;
{
pjsua_acc_config cfg;
pjsua_acc_config_default(&cfg);
cfg.id = pj_str("sip:" SIP_USER "#" SIP_DOMAIN);
cfg.reg_uri = pj_str("sip:" SIP_DOMAIN);
cfg.cred_count = 1;
cfg.cred_info[0].realm = pj_str(SIP_DOMAIN);
cfg.cred_info[0].scheme = pj_str("digest");
cfg.cred_info[0].username = pj_str(SIP_USER);
cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
cfg.cred_info[0].data = pj_str(SIP_PASSWD);
status = pjsua_acc_add(&cfg, PJ_TRUE, &acc_id);
if (status != PJ_SUCCESS){
//Error adding account
pjsua_destroy();
return -1;
}
}
/* make call to the URL. */
pj_str_t uri = pj_str(url);
status = pjsua_call_make_call(acc_id, &uri, 0, NULL, NULL, NULL);
if (status != PJ_SUCCESS){
//Error making call
pjsua_destroy();
return -1;
}
return address + 1;
}
Add SIP_WINPRT as a reference in SIP_UI project.
Call the SIP_WINPRT when the Call button is pressed.
Well, your problems doesn't seem to be related with PJSip but with UI Development.
I suggest that you create your UI (using XAML/C# or XAML/C++ and don't forget it must be a Windows Phone 8.0 Silverlight project). Then you start referencing the PJSip library.
Hope it helps!
Related
I'm taking a shot at using C++/WinRT to find and communicate with Bluetooth LE devices in a non-UWP app.
(I'm trying to avoid UWP, as there appear to be some constraints on what you can do with it, and it looks kind of bloated to me.)
My background is a lot of programming and releasing for small-group distribution old-fashioned C++ WinMain-based programming, as in Petzold's "Programming Windows 95". My experience has been using the Win32 API only.
Unfortunately for me, MS documentation indicates that Bluetooth LE is not supported in Win32, and only in WinRT. Thus, this forces me to use something like C++/WinRT to access the API.
So, I took a shot at it by downloading the only available example of bluetooth LE access in C++ which I know of at all, which is Microsoft's C++WinRT UWP example.
I got that running as one Visual Studio 2022 project, and, since I am looking for a non-UWP program, I tried putting the relevant stuff into another project, for which I used Microsoft VS2022's built-in template for a C++/WinRT Console. When I try to stick into that what appearVS says to be the key elements of the C++/WinRT UWP example, and make modifications to fix obvious problems, I have an error in the code which I have no idea how to fix: it is on the several get_weak() calls, which VS intellisense says are "undefined". (The compile also fails with unable to find main.g.h and main.g.cpp .
Here is the code:
File main.h:
#pragma once
#include "main.g.h"
class find_devs
{
find_devs() {};
private:
std::vector<Windows::Devices::Enumeration::DeviceInformation> UnknownDevices;
Windows::Devices::Enumeration::DeviceWatcher deviceWatcher{ nullptr };
event_token deviceWatcherAddedToken;
event_token deviceWatcherUpdatedToken;
event_token deviceWatcherRemovedToken;
event_token deviceWatcherEnumerationCompletedToken;
event_token deviceWatcherStoppedToken;
void StartBleDeviceWatcher();
void StopBleDeviceWatcher();
std::vector<Windows::Devices::Enumeration::DeviceInformation>::iterator FindUnknownDevices(hstring const& id);
fire_and_forget DeviceWatcher_Added(Windows::Devices::Enumeration::DeviceWatcher sender, Windows::Devices::Enumeration::DeviceInformation deviceInfo);
fire_and_forget DeviceWatcher_Updated(Windows::Devices::Enumeration::DeviceWatcher sender, Windows::Devices::Enumeration::DeviceInformationUpdate deviceInfoUpdate);
fire_and_forget DeviceWatcher_Removed(Windows::Devices::Enumeration::DeviceWatcher sender, Windows::Devices::Enumeration::DeviceInformationUpdate deviceInfoUpdate);
fire_and_forget DeviceWatcher_EnumerationCompleted(Windows::Devices::Enumeration::DeviceWatcher sender, Windows::Foundation::IInspectable const&);
fire_and_forget DeviceWatcher_Stopped(Windows::Devices::Enumeration::DeviceWatcher sender, Windows::Foundation::IInspectable const&);
};
and main.cpp:
#include "pch.h"
using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::Devices::Enumeration;
#include "pch.h"
#include "main.h"
#include "main.g.cpp"
using namespace winrt;
using namespace Windows::Devices::Enumeration;
using namespace Windows::Foundation;
namespace winrt
{
hstring to_hstring(DevicePairingResultStatus status)
{
switch (status)
{
case DevicePairingResultStatus::Paired: return L"Paired";
case DevicePairingResultStatus::NotReadyToPair: return L"NotReadyToPair";
case DevicePairingResultStatus::NotPaired: return L"NotPaired";
case DevicePairingResultStatus::AlreadyPaired: return L"AlreadyPaired";
case DevicePairingResultStatus::ConnectionRejected: return L"ConnectionRejected";
case DevicePairingResultStatus::TooManyConnections: return L"TooManyConnections";
case DevicePairingResultStatus::HardwareFailure: return L"HardwareFailure";
case DevicePairingResultStatus::AuthenticationTimeout: return L"AuthenticationTimeout";
case DevicePairingResultStatus::AuthenticationNotAllowed: return L"AuthenticationNotAllowed";
case DevicePairingResultStatus::AuthenticationFailure: return L"AuthenticationFailure";
case DevicePairingResultStatus::NoSupportedProfiles: return L"NoSupportedProfiles";
case DevicePairingResultStatus::ProtectionLevelCouldNotBeMet: return L"ProtectionLevelCouldNotBeMet";
case DevicePairingResultStatus::AccessDenied: return L"AccessDenied";
case DevicePairingResultStatus::InvalidCeremonyData: return L"InvalidCeremonyData";
case DevicePairingResultStatus::PairingCanceled: return L"PairingCanceled";
case DevicePairingResultStatus::OperationAlreadyInProgress: return L"OperationAlreadyInProgress";
case DevicePairingResultStatus::RequiredHandlerNotRegistered: return L"RequiredHandlerNotRegistered";
case DevicePairingResultStatus::RejectedByHandler: return L"RejectedByHandler";
case DevicePairingResultStatus::RemoteDeviceHasAssociation: return L"RemoteDeviceHasAssociation";
case DevicePairingResultStatus::Failed: return L"Failed";
}
return L"Code " + to_hstring(static_cast<int>(status));
}
}
// This scenario uses a DeviceWatcher to enumerate nearby Bluetooth Low Energy devices,
// displays them in a ListView, and lets the user select a device and pair it.
// This device will be used by future scenarios.
// For more information about device discovery and pairing, including examples of
// customizing the pairing process, see the DeviceEnumerationAndPairing sample.
#pragma region UI Code
#pragma endregion
#pragma region Device discovery
/// <summary>
/// Starts a device watcher that looks for all nearby Bluetooth devices (paired or unpaired).
/// Attaches event handlers to populate the device collection.
/// </summary>
void find_devs::StartBleDeviceWatcher()
{
// Additional properties we would like about the device.
// Property strings are documented here https://msdn.microsoft.com/en-us/library/windows/desktop/ff521659(v=vs.85).aspx
auto requestedProperties = single_threaded_vector<hstring>({ L"System.Devices.Aep.DeviceAddress", L"System.Devices.Aep.IsConnected", L"System.Devices.Aep.Bluetooth.Le.IsConnectable" });
// BT_Code: Example showing paired and non-paired in a single query.
hstring aqsAllBluetoothLEDevices = L"(System.Devices.Aep.ProtocolId:=\"{bb7bb05e-5972-42b5-94fc-76eaa7084d49}\")";
deviceWatcher =
Windows::Devices::Enumeration::DeviceInformation::CreateWatcher(
aqsAllBluetoothLEDevices,
requestedProperties,
DeviceInformationKind::AssociationEndpoint);
// Register event handlers before starting the watcher.
deviceWatcherAddedToken = deviceWatcher.Added({ get_weak(), &DeviceWatcher_Added });
deviceWatcherUpdatedToken = deviceWatcher.Updated({ get_weak(), &DeviceWatcher_Updated });
deviceWatcherRemovedToken = deviceWatcher.Removed({ get_weak(), &DeviceWatcher_Removed });
deviceWatcherEnumerationCompletedToken = deviceWatcher.EnumerationCompleted({ get_weak(), &DeviceWatcher_EnumerationCompleted });
deviceWatcherStoppedToken = deviceWatcher.Stopped({ get_weak(), &DeviceWatcher_Stopped });
// Start the watcher. Active enumeration is limited to approximately 30 seconds.
// This limits power usage and reduces interference with other Bluetooth activities.
// To monitor for the presence of Bluetooth LE devices for an extended period,
// use the BluetoothLEAdvertisementWatcher runtime class. See the BluetoothAdvertisement
// sample for an example.
deviceWatcher.Start();
}
/// <summary>
/// Stops watching for all nearby Bluetooth devices.
/// </summary>
void find_devs::StopBleDeviceWatcher()
{
if (deviceWatcher != nullptr)
{
// Unregister the event handlers.
deviceWatcher.Added(deviceWatcherAddedToken);
deviceWatcher.Updated(deviceWatcherUpdatedToken);
deviceWatcher.Removed(deviceWatcherRemovedToken);
deviceWatcher.EnumerationCompleted(deviceWatcherEnumerationCompletedToken);
deviceWatcher.Stopped(deviceWatcherStoppedToken);
// Stop the watcher.
deviceWatcher.Stop();
deviceWatcher = nullptr;
}
}
std::vector<Windows::Devices::Enumeration::DeviceInformation>::iterator FindUnknownDevices(hstring const& id)
{
}
fire_and_forget find_devs::DeviceWatcher_Added(DeviceWatcher sender, DeviceInformation deviceInfo)
{
}
fire_and_forget find_devs::DeviceWatcher_Updated(DeviceWatcher sender, DeviceInformationUpdate deviceInfoUpdate)
{
// Protect against race condition if the task runs after the app stopped the deviceWatcher.
if (sender == deviceWatcher)
{
auto deviceInfo = FindUnknownDevices(deviceInfoUpdate.Id());
if (deviceInfo != UnknownDevices.end())
{
deviceInfo->Update(deviceInfoUpdate);
// If device has been updated with a friendly name it's no longer unknown.
}
}
}
fire_and_forget find_devs::DeviceWatcher_Removed(DeviceWatcher sender, DeviceInformationUpdate deviceInfoUpdate)
{
// Protect against race condition if the task runs after the app stopped the deviceWatcher.
if (sender == deviceWatcher)
{
auto deviceInfo = FindUnknownDevices(deviceInfoUpdate.Id());
if (deviceInfo != UnknownDevices.end())
{
UnknownDevices.erase(deviceInfo);
}
}
}
fire_and_forget find_devs::DeviceWatcher_EnumerationCompleted(DeviceWatcher sender, IInspectable const&)
{
// Protect against race condition if the task runs after the app stopped the deviceWatcher.
if (sender == deviceWatcher)
{
}
}
fire_and_forget DeviceWatcher_Stopped(DeviceWatcher sender, IInspectable const&)
{
// Access this->deviceWatcher on the UI thread to avoid race conditions.
auto lifetime = get_strong();
co_await resume_foreground(Dispatcher());
// Protect against race condition if the task runs after the app stopped the deviceWatcher.
if (sender == deviceWatcher)
{
}
}
#pragma endregion
int main()
{
init_apartment();
Uri uri(L"http://aka.ms/cppwinrt");
printf("Hello, %ls!\n", uri.AbsoluteUri().c_str());
}
and, for completeness, this is pch.h
#pragma once
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Devices.Enumeration.h>
The code is, I know, not complete. I haven't created a DeviceWatcher, etc., but I am apparently blocked in that I can't get the get_weaks() to pass intellisense screening or to compile.
Any guidance from people who know about this stuff would be great.
Bear in mind: I, myself, pretty much don't know what's going on. Due to the complexity, from my Win32 Petzold-style background, of the example MS C++/WinRT UWP example. It has all kinds of stuff in the Solution Explorer. There are .idl files, a packages.config, a bunch of different Xaml files, some generated c++ files. All this stuff is beyond my understanding, and I have not been able to pick it up with any speed from the MS documentation I can find.
(All I have figured out is that C++/WinRT is some sort of a thing where there are generated header and perhaps other files that are supposed to make your C++ code look like it's directly accessing WinRT classes. And, I have seen MS write that you can use winRT in non-UWP applications. Otherwise, I am lost.)
I am beginner in Embarcadero C++, If my application is developed in Embarcadero C++ and installed in client machine then how my application notify user if new update is available? If user clicked on yes button then it will first download the application then install it.
Please let me know if anybody have any Idea.
Here is how I check if new version of program is available on the server, using
Indy Client component TIdHTTP.
Let's say you have uploaded a new version of your application. Besides installation or zip file containing you application, upload a one line text file (applicationBuildData.txt) which contains build value (integer), delimiter (;) and optionally some other data (version number, program name, etc...). For example:
20170215; ProgamName rel. 1.2.
This is the only line in applicationBuildData.txt file. Here is the code sample (I've modified my original code a bit):
void __fastcall TfrmDialog::Button1Click(TObject *Sender)
{
TIdHTTP *IdHTTP1 = new TIdHTTP(this);
// let's say this is current app build (on user's side)
int currAppBuild = 20170101;
int prodBuildNew = 0;
UnicodeString prodVersionNew;
UnicodeString version_str;
try {
// get content of applicationBuildData.txt into string
version_str = IdHTTP1->Get("http://www.your-site.com/applicationBuildData.txt");
prodBuildNew = StrToInt(version_str.SubString(1, version_str.Pos(";") - 1).Trim());
prodVersionNew = version_str.SubString(version_str.Pos(";") + 1, 100).Trim();
}
catch (...)
{
prodBuildNew = 0;
prodVersionNew = "???";
}
if (prodBuildNew == 0) {
// ...faild to get data from server...
// display message
}
else if (prodBuildNew > currAppBuild) {
// new version is available
// display message
}
else {
// application version is up to date
// display message
}
delete IdHTTP1;
}
In this example, current build number is smaller then uploaded build number and it will indicate user that new version is available.
Note: currAppBuild is usually some global constant, or global variable that presents build version. After new version on the server is detected, you can either download installation/zip or simply display message and let the user go to your site and download new version manually.
Edit: How to download the file to your local disk using TIdHTTP component, check the following video:
https://www.youtube.com/watch?v=fcN8K3R4iZE
My team owns a Chrome extension, and the other team has a similar extension but sooner will be deprecated, so we will take over all their existing users. Here comes the question - is there a way to migrate users from their extension to ours seamless? I.e. is there a way to auto-upgrade to our extension from user end?
There is no seamless way, as for obvious security reasons extensions can't install other extensions (even with "management" permission), but here's a possible upgrade path.
I'll call the "old" extension A and assume its ID is "extension_a_id", and the "new" extension B and assume its ID is `extension_b_id".
Make sure that extensions can talk to each other. Unless you specifically define "externally_connectable" in the manifest, that should be the case by default; if you do, make sure that extension B's includes the "extension_a_id" ID and vice versa.
Update extension B to include code responding to requests from A in all following steps. Do not proceed until you're reasonably sure most of the install base has this version (maybe wait a week or so).
//// Extension B (background code) ////
chrome.runtime.onMessageExternal.addListener(
function(message, sender, sendResponse) {
if(sender.id && sender.id == "extension_A_id") {
/* ..processing code.. */
}
}
);
In extension A, add a check that extension B is installed. Do so by pinging it:
//// Extension A ////
chrome.runtime.onStartup.addListener(function() {
isNewInstalled(function(response) {
if(response) {
transferPreferences(response.versionB); // See step 5
} else {
// Nag user to install, see step 4
}
});
});
function isNewInstalled(callback) {
chrome.runtime.sendMessage(
"extension_B_id",
{areYouThere: true},
passResponseOrFalse(callback)
);
}
function passResponseOrFalse(callback) {
return function(response) {
// It's important to evaluate chrome.runtime.lastError
// to prevent uncatchable exception, see http://stackoverflow.com/q/28431505
if(chrome.runtime.lastError || !response) {
callback(false);
} else {
callback(response);
}
}
}
//// Extension B (processing code) ////
// Send version number just in case
if(message.areYouThere) sendResponse({
versionB: chrome.runtime.getManifest().version
});
If extension B is not installed in step 3, nag the user to install it: show a page that explains why it is needed to upgrade and link to the CWS listing. This step requires user input.
If the extension B is already installed in step 3, transfer user options over and self-uninstall:
//// Extension A ////
function transferPreferences(versionB) {
/* ..validate version of B.. */
var prefs = {};
/* ..fill prefs with data that needs to be transfered (JSON-encodable).. */
chrome.runtime.sendMessage(
"extension_B_id",
{
versionA: chrome.runtime.getManifest().version,
preferences: prefs
},
passResponseOrFalse(goodbyeCruelWorld)
);
}
function goodbyeCruelWorld(response) {
if(response.processed) {
// Does not require management permission
chrome.management.uninstallSelf();
} else {
console.warn("It is not my time to die yet.");
}
}
//// Extension B, processing code ////
if(message.preferences) {
/* ..validate message.versionA and process message.preferences.. */
sendResponse({processed: true});
}
When extension B is installed, message the (possibly installed) extension A that the transfer can start immediately:
//// Extension B, background code ////
chrome.runtime.onInstalled.addListener(function(details) {
/* ..maybe check details.reason and new version.. */
chrome.runtime.sendMessage(
"extension_A_id",
{iAmHere: true, versionB: chrome.runtime.getManifest().version},
ignoreResponse
);
});
function ignoreResponse(response) {
// Again, evaluate to avoid exceptions;
// if needed, this is the place to check if A is still installed
return chrome.runtime.lastError;
}
//// Extension A, background code ////
chrome.runtime.onMessageExternal.addListener(
function(message, sender, sendResponse) {
if(sender.id && sender.id == "extension_B_id") {
if(message.iAmHere) {
sendResponse({
versionA: chrome.runtime.getManifest().version
});
transferPreferences(message.versionB);
}
}
}
);
Publish an update to extension B with all of the above.
Result:
Users that have B installed won't notice anything, since ignoreResponse will gobble up the messaging error;
Users that have both installed will initiate transfer as soon as B updates and it will quietly finish;
Users that only have A will be nagged on every extension restart to install B instead, upon which the transfer will start automatically.
One last concern is not to clobber the preferences of B with ones from A; left as an exercise to the reader (and also depends on the implementation).
I have followed this tutorial on setting up Parse push notification in a Windows Phone app. This is my code:
public App() {
// Global handler for uncaught exceptions.
UnhandledException += Application_UnhandledException;
// Standard XAML initialization
InitializeComponent();
// Phone-specific initialization
InitializePhoneApplication();
// Language display initialization
InitializeLanguage();
// Show graphics profiling information while debugging.
if (Debugger.IsAttached) {
// Display the current frame rate counters.
Application.Current.Host.Settings.EnableFrameRateCounter = true;
// Show the areas of the app that are being redrawn in each frame.
//Application.Current.Host.Settings.EnableRedrawRegions = true;
// Enable non-production analysis visualization mode,
// which shows areas of a page that are handed off to GPU with a colored overlay.
//Application.Current.Host.Settings.EnableCacheVisualization = true;
// Prevent the screen from turning off while under the debugger by disabling
// the application's idle detection.
// Caution:- Use this under debug mode only. Application that disables user idle detection will continue to run
// and consume battery power when the user is not using the phone.
PhoneApplicationService.Current.UserIdleDetectionMode = IdleDetectionMode.Disabled;
}
// Initialize the Parse client with your Application ID and .NET Key found on
// your Parse dashboard
ParseClient.Initialize("grpTmrClet8K35yeXg2HQKK8wl59VeC9ijH0I0dn", "os8EfSFq9maPBtDJ91Mq0xnWme8fLANhttTPAqKu");
// After calling ParseClient.Initialize():
this.Startup += async (sender, args) =>
{
// This optional line tracks statistics around app opens, including push effectiveness:
ParseAnalytics.TrackAppOpens(RootFrame);
// By convention, the empty string is considered a "Broadcast" channel
// Note that we had to add "async" to the definition to use the await keyword
await ParsePush.SubscribeAsync("testchannel");
};
}
// Code to execute when the application is launching (eg, from Start)
// This code will not execute when the application is reactivated
private async void Application_Launching(object sender, LaunchingEventArgs e) {
await ParseAnalytics.TrackAppOpenedAsync();
}
When I send a push notification from the Parse dashboard it doesn't get received. I have tried running both on the emulator (Windows Phone 8.0) and device (8.1), with app in foreground, background and closed with the same negative result.
When I use a channel like "testchannel" above and use the segment options, the channel name appears in the dropdown list of options indicating that the app is at least connecting Parse, but it just wont receive the notifications.
Hope someone can help me identify what I am missing. Thanks in advance.
If you are developing a Windows Phone 8.1 app, make sure you've enabled toast notification in the manifest file.
I don't quite understand everything about Parse just yet, but this is what works for me.
In App.xaml.cs:
public App()
{
this.InitializeComponent();
this.Suspending += this.OnSuspending;
ParseClient.Initialize("wSjuNTbtjVLRaedXvOoaf9S5cTbkuQohTulNZ2vS", "nWZMhXRet9Wotlgikb9aUdKf5GFtRiMvduw7w68z");
}
We subscribe and enable analytics OnLaunched:
protected async override void OnLaunched(LaunchActivatedEventArgs e)
//Generated codes go here
await ParsePush.SubscribeAsync("testchannel");
await ParseAnalytics.TrackAppOpenedAsync();
That would simply do the trick. You should modify the code according to your needs. Hope this helps.
I have my ActiveX COM component developed in VC6. I have created the firebreath plugin over it to be able to call the COM API from different browsers. I have one API in ActiveX component which pops up the CDialog UI, On Google Chrome browser dlg.DoModal() function is failing. Issue is only with Chrome it simply crashes at this call, in other browsers its working perfectly
On Windows 7 its working with Google Chrome as well issue is with Windows XP.
Please provide me some feedback on this issue.
I am attaching some code snippets here to give some idea of what I am trying to do
Firebreath Plugin code (Plugin name is FBTest):
bool FBTest::onWindowAttached(FB::AttachedEvent *evt, FB::PluginWindow *piw)
{
// The window is attached; act appropriately
try {
/* Now that we have the plugin window, create the ActiveX container
window as a child of the plugin, then create the ActiveX control
as a child of the container.
*/
FB::PluginWindowWin* pwnd = piw->get_as<FB::PluginWindowWin>();
if(pwnd != NULL)
{
HWND hWnd = pwnd->getHWND();
if(hWnd)
{
// Create the ActiveX control container
RECT rc;
::GetClientRect(hWnd, &rc);
m_fbTestWin.Create(hWnd, &rc, 0, WS_VISIBLE|WS_CHILD);
CComPtr<IUnknown> spControlTest;
//ETESTPROGID is prog id of activex component
HRESULT hrTest = m_fbTestWin.CreateControlEx(ETESTPROGID, NULL, NULL, &spControlTest, GUID_NULL, NULL);
if(SUCCEEDED(hrTest) && (spControlTest != NULL))
{
spControlTest.QueryInterface(&m_eTestAxCtl);
g_eTestAxCtl = m_eTestAxCtl;
if (m_eTestAxCtl)
{
//TODO: should we throw a FB exception here?
}
}
}
}
} catch(...) {
//TODO: should we throw a FB exception here?
}
return false;
}
void FBTest::TestFunc()
{
//hThread = (HANDLE)_beginthreadex(NULL, 0,&FBTest::Start, (void*)&m_eTestAxCtl, 0, &ThreadId);
if(m_eTestAxCtl)
{
try {
long nCode = -1;
//This is call to API of Activex component which will popup the dialog
HRESULT hr = m_eTestAxCtl->TestFunc();
//return nCode;
}
catch(...) {
}
}
}
Activex Component code :
STDMETHODIMP CTest::TestFunc()
{
//CTestDlg is ATL Dialog Object
CTestDlg TestDlg;
//At this call Google chrome is crashing
if(!TestDlg.DoModal())
return S_FALSE;
return S_OK;
}
I am calling TestFunc() API of plugin from one HTML page and its showing me the dailog in IE and firefox browsers but Chrome is crashing..
Please help.
Since you've given no info on when or how you're calling it, it's hard to be sure, but my guess is that you're calling DoModal on the main thread. That will cause the main thread to block.
You must never block the main thread in a plugin.
Try calling it on a different thread.