Push notifications in codename one - codenameone

I am at the final stage of my codename one app now and this final stage is to implement push notifications.
I need some help on how to implement the client side for push notifications.
I have followed the section in the developer guide and my main class implements PushCallback.
I also have the relevant methods implemented as below:
public void start() {
if(current != null){
current.show();
return;
}
Display.getInstance().callSerially(() -> Display.getInstance().registerPush());
showHomeForm();
}
#Override
public void push(String value) {
Dialog.show("Received Push", value, "OK", null);
}
#Override
public void registeredForPush(String deviceId) {
Dialog.show("Push Registered", "Device ID: " + deviceId + "\nDevice Key: " + Push.getDeviceKey() , "OK", null);
}
#Override
public void pushRegistrationError(String error, int errorCode) {
Dialog.show("Push Error", "" + error, "OK", null);
}
My understanding is that the registeredForPush method should be invoked when calling the registerPush method. When I start the app the registeredForPush method is not called and the registerPush method seems to do nothing.
What is incorrect in my understanding?

You shouldn't use a Dialog in these callbacks as a dialog call is blocking and might cause a failure because of the nature of these API's e.g. an API can be invoked when the app is minimized.
registerPush() triggers the registration and should eventually invoke either the registered or the error method.
I'm guessing you are running on the simulator where push isn't actually implemented. You can use the new push console that allows you to simulate it by invoking the registered callbacks and send push messages to the simulator. These will only work on the devices.

Related

Asynchronous Camel Component - doStop() called immediately

I am trying to create a camel component which consumes an API from an external service.
My Route is as follows
from("myComponent:entity?from=&to=")
.to("seda:one")
from("seda:one")
.aggregate(constant(true), new GroupedBodyAggregationStrategy())
.completionSize(5)
.completionTimeout(5000)
.process( new Processor1() )
to("seda:two")
.
.
.
from("seda:five")
.to("myComponent2:entity")
I implemented my component consumer as follows
public class MyComponentConsumer extends DefaultConsumer {
public MyComponentConsumer(MyComponentEndpoint endpoint, Processor processor) {
super(endpoint, processor);
}
#Override
protected void doStart() throws Exception {
super.doStart();
flag = true;
while ( flag ) {
//external API call
Resource resource = getNextResource();
if ( resource.next() == null ) {
flag = false;
}
Exchange ex = endpoint.createExchange(ExchangePattern.InOnly);
ex.getIn().setBody(resource.toString());
getAsyncProcessor().process(
ex
doneSync -> {
LOG.info("Message processed");
}
);
}
}
#Override
protected void doStop() throws Exception {
super.doStop();
System.out.println("stop ---- ");
}
}
Everything worked fine and the data was propogating through the route. My only problem was that data did not propogate to the next part until the whole of this process was completed. And the next parts were running asynchronously.
I looked at the example of StreamConsumer and tried to implement it to my code using a runnable and an executorService. But if I do that consumer stops as soon as it starts.
I changed the code to
public class MyComponentConsumer extends DefaultConsumer implements Runnable
and added
private ExecutorService executor;
getEndpoint().getCamelContext().getExecutorServiceManager().newSingleThreadExecutor(this, "myComponent");
executor.execute(this);
and moved my logic inside the run() method. But, the consumer thread ends as soon as it starts. and the async processor does not transfer the data properly.
Is there any other way to implement the functionality I need or am I mistaken somewhere here. Any help would be appreciated.
What version of camel are you using?
There was an issue with managing the state of consumer in camel 2.x which was fixed in camel 3.x CAMEL-12765 which can lead to the issue you are describing here.
If you are on camel 2.x try using newScheduledThreadPool instead of newSingleThreadExecutor.
Also executor.schedule(this, 5L, TimeUnit.SECONDS) instead of executor.execute(this).
Delayed start of executor might help avoid the problem you are facing.

CodenameOne IntentResultListener not being called

I have been trying to call an oAuth evernote library without success. The authentication works but my Codename One app is not notified via the startActivityForResult() mechanism. I have trimmed out as many factors as I can. I have currently reduced it to startActivityForResult() using the Contact application.
I now have a Codename One native class with the following code. (This is an example from https://developer.android.com/guide/components/intents-common.html).
private void selectContact() {
debugOut ("selectContact: Entry");
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType(ContactsContract.Contacts.CONTENT_TYPE);
AndroidNativeUtil.startActivityForResult(intent, new IntentResultListener() {
public void onActivityResult (int requestCode, int resultCode, Intent data) {
debugOut ("onActivityResult: Entry");
}
});
debugOut ("selectContact: Exit");
}
A call to selectContact() launches the Contact application. When I pick a Contact, the Contact application closes. The system console shows both messages: "selectContact: Entry" and "selectContact: Exit".
The code in IntentResultListener.onActivityResult() is not called (ie ""onActivityResult: Entry" is not output).
I have tried to look at the Codename One source on GitHub (CodenameOneActivity.java), in particular this:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//is this a payment result
if (mHelper != null && mHelper.handleActivityResult(requestCode, resultCode, data)) {
return;
}
IntentResult response = new IntentResult(requestCode, resultCode, data);
intentResult.add(response);
}
I'm likely looking in the wrong place but this does not appear to forward received Intents if it is not interested. (I am making an assumption that the cloud build uses CodenameOneActivity to build the Android app).
I think this effectively broke that functionality. I've filed an issue to track this.

(Android Studio) Connecting an app to Google Endpoints Module

I'm having trouble following the second step here.
I really don't understand how this sample does anything other than return a simple toast message. How does it utilize the API to display that message?
class EndpointsAsyncTask extends AsyncTask<Pair<Context, String>, Void, String> {
private static MyApi myApiService = null;
private Context context;
#Override
protected String doInBackground(Pair<Context, String>... params) {
if(myApiService == null) { // Only do this once
MyApi.Builder builder = new MyApi.Builder(AndroidHttp.newCompatibleTransport(),
new AndroidJsonFactory(), null)
// options for running against local devappserver
// - 10.0.2.2 is localhost's IP address in Android emulator
// - turn off compression when running against local devappserver
.setRootUrl("http://10.0.2.2:8080/_ah/api/")
.setGoogleClientRequestInitializer(new GoogleClientRequestInitializer() {
#Override
public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest) throws IOException {
abstractGoogleClientRequest.setDisableGZipContent(true);
}
});
// end options for devappserver
myApiService = builder.build();
}
context = params[0].first;
String name = params[0].second;
try {
return myApiService.sayHi(name).execute().getData();
} catch (IOException e) {
return e.getMessage();
}
}
#Override
protected void onPostExecute(String result) {
Toast.makeText(context, result, Toast.LENGTH_LONG).show();
}
I'm afraid my this sample is too complex for my limited knowledge. How exactly do I "talk" to the Google Endpoints Module when running an app? Specifically, What is EndpointsAsyncTask();?
Are there any resources listing all the methods available to me? Is there a simpler example of an app communicating with a Google Cloud Endpoint?
The service methods available to you are defined by the backend source in section 1.
In the example you posted, this line: myApiService.sayHi(name).execute()
is an actual invocation call to the backend that you defined by annotating #ApiMethod("sayHi") on the method in the MyEndpoint.java class of your backend module.
The reason your Android app defines an EndpointsAsyncTask is because slow operations such as calls that hit the network need to happen off of the UI thread to avoid locking the UI. The demo simply puts the returned value into a Toast but you could modify onPostExecute() to do whatever you'd like with the result.
For more info on Google Endpoints check out:
https://cloud.google.com/appengine/docs/java/endpoints/
And for info about using an Android AsyncTask look here:
http://developer.android.com/reference/android/os/AsyncTask.html

Duplex WCF Client does not work with WinForms or WPF, but works fine with Console

I have a very peculiar case here.
I have implemented a wsDualHttpBinding WCF duplex server that is being consumed by a Windows Service.
The contract and implementation on the server side is defined as follows:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class FixServerContract : IFixContract
{
public FixServerContract()
{
}
public void Requestlogin(string message)
{
try
{
IServerCallback callback = OperationContext.Current.GetCallbackChannel<IServerCallback>();
callback.BroadcastToClient("Greetings from server");
}
catch (Exception ex)
{
}
}
[ServiceContract(CallbackContract=typeof(IServerCallback))]
public interface IFixContract
{
[OperationContract]
void Requestlogin(string message);
}
public interface IServerCallback
{
[OperationContract(IsOneWay = true)]
void BroadcastToClient(string eventData);
}
On the client end, I also have a single callback class, with the attached callback interface accessed by adding a Service Reference to the Client project as follows:
class MyCallbackClass : IFixContractCallback
{
public void RegisterClient()
{
InstanceContext context = new InstanceContext(this);
FixContractClient proxy = new FixContractClient(context);
proxy.Requestlogin("hello");
}
public void BroadcastToClient(string eventData)
{
}
}
When proxy.RequestLogin("hello"); is called by the client, the server should respond by signaling BroadcastToClient(string eventData)
But, here is where the peculiar behavior begins!
When my client calls RegisterClient directly from Main, outside of a Winform or WPF environment, everything works as it should be. That is, RequestLogin is successfully called to the server, and the server successfully responds by signalling BroadcastToClient on the client end.
This is shown here:
[STAThread]
private static void Main(string[] args)
{
MyCallbackClass callbackClass = new MyCallbackClass();
callbackClass.RegisterClient();
}
However, when I do the following below simply by wrapping the above lines inside an button_Click handler in the Winform, this bug manifests itself with a crash:
[STAThread]
private static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
and then have a button click do the rest like so:
private void button1_Click(object sender, EventArgs e)
{
MyCallbackClass callbackClass = new MyCallbackClass();
callbackClass.RegisterClient();
}
then the following bug manifests itself:
1) RequestLogin is called on the server side, but the call to BroadcastToClient never reaches the client. Further to this, the RequestLogin never returns to client side, but instead, will timeout with the following exception:
2) An unhandled exception of type 'System.TimeoutException' occurred in mscorlib.dll. This request operation sent to XXXX did not receive a reply within the configured timeout (00:00:59.6359791). The time allotted to this operation may have been a portion of a longer timeout. This may be because the service is still processing the operation or because the service was unable to send a reply message. Please consider increasing the operation timeout (by casting the channel/proxy to IContextChannel and setting the OperationTimeout property) and ensure that the service is able to connect to the client.
The same behavior occurs if I use a WPF client. On the otherhand, it works perfectly if I use a Console based client!
Why does my Duplex Callback only work outside of a Winform or WPF?
How should I go about resolving this issue?
I am at my witts end here.
Thanks.
Kudos to this individual who has supplied me with an answer:
https://groups.google.com/forum/#!topic/microsoft.public.dotnet.framework.webservices/8Y6C8dRCFws
The solution is to modify MyCallbackClass as follows:
[CallbackBehavior(UseSynchronizationContext = false)]
class MyCallbackClass : IFixContractCallback
{
public void RegisterClient()
{
MyCallbackClass tester = this;
InstanceContext context = new InstanceContext(this);
FixContractClient proxy = new FixContractClient(context);
proxy.Requestlogin("hello");
}
public void BroadcastToClient(string eventData)
{
}
}

WPF + PRISM - Cannot 'LoadModule' in separate thread

I have a WPF application in PRISM architecture.
I have a 'Login View' that is shown in the 'Main Region' when the app loads.
When the user presses 'Login' - I connect to a WCF service, authenticate the user, and get a list of roles for that user from the service.
Then - according to the user's roles - I load different modules, using the 'Module Manager'.
Problem is - I want all the work after the 'Login' button is pressed to be done in a separate thread, because it might take time to connect to the service etc, and I don't want the UI to be frozen.
But - if I put the code to 'connect, authenticate, get roles, load modules' in a separate thread - I get an exception when I call '_moduleManager.LoadModule' that says:
The calling thread must be STA, because many UI components require this.
How can I solve this ?
I have tried different solutions.
I have tried to set the new thread's 'Apartment State = STA' and it didn't help.
I thought about saving the 'Dispatcher' object in the constructor of the View-Model, and then do 'dispatcher.Invoke' when I call 'LoadModule', but that is bad design (View-Model should not use Dispatcher, and also it is bad for testing).
Any ideas how I can solve this ??
Only the 'LoadModule' gives me grief, all the other stuff works fine.
.
[Update] - Added Code Sample :
[Export]
public class LoginViewModel : NotificationObject
{
[ImportingConstructor]
public LoginViewModel(IRegionManager regionManager, IModuleManager moduleManager)
{
this.LoginCommand = new DelegateCommand(LoginExecute, LoginCanExecute);
this._regionManager = regionManager;
this._moduleManager = moduleManager;
}
private void LoginExecute()
{
IsBusy = true; // Set this to 'true' so controls go disabled
LoginStatus = ""; // Clear the 'login status' string
Thread loginThread = new Thread(new ThreadStart(LoginWork));
loginThread.SetApartmentState(ApartmentState.STA);
loginThread.Start();
}
private void LoginWork()
{
ParamsToGetRoles param = new ParamsToGetRoles
{
Username = Username,
InputtedPassword = Password
};
try
{
// Connect to the secure service, and request the user's roles
_clientSecure = new AuthenticationServiceClient("WSHttpBinding_MyService");
_clientSecure.ClientCredentials.UserName.UserName = param.Username;
_clientSecure.ClientCredentials.UserName.Password = param.InputtedPassword;
_clientSecure.ChannelFactory.Faulted += new EventHandler(ChannelFactory_Faulted);
var local = _clientSecure.ChannelFactory.CreateChannel();
_clientSecure.GetRolesCompleted += new EventHandler<GetRolesCompletedEventArgs>(clientSecure_GetRolesCompleted);
_clientSecure.GetRolesAsync(param);
}
catch (Exception ex)
{
Console.WriteLine("Exception : " + ex.Message.ToString());
}
}
void clientSecure_GetRolesCompleted(object sender, GetRolesCompletedEventArgs e)
{
if (e.Error == null)
{
_clientSecure.Close();
LoginSuccess(e.Result.UserRoles);
}
else
{
LoginFailure("Unable to authenticate");
}
_clientSecure = null;
}
private void LoginSuccess(List<UserTypeEnum> rolesOfAuthenticatedUser)
{
LoginStatus = "Success";
if (rolesOfAuthenticatedUser.Contains(UserTypeEnum.Administrator))
{
// This is what throws the exception !
// This is called by the 'EndInvoke' of the 'GetRoles' operation,
// Which was called in the 'LoginWork' function which was run on a separate thread !
_moduleManager.LoadModule(WellKnownModuleNames.ModuleAdmin);
}
NavigateToMainMenu();
this.IsBusy = false;
}
}
You should attach the debugger and inspect the threads window with a breakpoint set at clientSecure_GetRolesCompleted. I'm pretty sure it is not being called from the loginThread: while LoginWork does run in the loginThread, it then adds an eventhandler to the completion event of an async operation. Async = runs in yet another thread.
So what probably happens:
LoginExecute executes in the UI thread
starts a seperate thread B to run LoginWork
calls GetRolesAsync so start a thread C (which is not STA) to get the roles
thread C eventually calls 'clientSecure_GetRolesCompleted', not thread B
So, you do not need a seperate thread for LoginWork since the actual work is already done as an async operation. To get around the loading issue, either try to make the 'get roles' thread STA, or better, use a dispatcher so LoginSuccess gets invoked on the UI thread.

Resources