I use this method to close my app:
public void quit()
{
if (NavigationService.CanGoBack)
{
while (NavigationService.RemoveBackEntry() != null)
{
NavigationService.RemoveBackEntry();
}
}
}
When I call it after pressing back key, the app closes as intended:
protected override void OnBackKeyPress(CancelEventArgs e)
{
quit();
}
But anywhere else I call this method, the stack is emptied but the app will not close.
If I try:
quit();
NavigationService.GoBack();
There will be a runtime error. If anybody can help me because I don't like to through an exception since it will be recorded as a bug in the marketplace statistics.
There is no need to clear the Navigation stack; if the application terminates the navigation stack will be gone. Do not worry about the user going forward; there is no forward key.
To remove the exception:
quit();
if( NavigationService.CanGoBack)
{
NavigationService.GoBack();
}
But before you do this, look at the code: what are you trying to accomplish? First you are cleaning out the stack and then you want to use the stack.
Related
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.
I guess most of us agree, that NIO2 is a fine thing to make use of. Presumed you want to monitor some part of the file system for incoming xml - files it is an easy task now. But what if I want to integrate the things into an existing Java EE application so I don't have to start another service (app-server AND the one which monitors the file system)?
So I have the heavy weight app-server with all the EJB 3.1 stuff and some kind of service monitoring the file system and take appropriate action once a file shows up. Interestingly the appropriate action is to create a Message and send it by JMS and it might be nice to integrate both into the app server.
I tried #Startup but deployment freezes (and I know that I shouldn't make use of I/O in there, was just a try). Anyhow ... any suggestions?
You could create a singleton that loads at startup and delegates the monitoring to an Asynchronous bean
#Singleton
#Startup
public class Initialiser {
#EJB
private FileSystemMonitor fileSystemMonitor;
#PostConstruct
public void init() {
String fileSystemPath = ....;
fileSystemMonitor.poll(fileSystemPath);
}
}
Then the Asynchronous bean looks something like this
#Stateless
public class FileSystemMonitor {
#Asynchronous
public void poll(String fileSystemPath) {
WatchService watcher = ....;
for (;;) {
WatchKey key = null;
try {
key = watcher.take();
for (WatchEvent<?> event: key.pollEvents()) {
WatchEvent.Kind<?> kind = event.kind();
if (kind == StandardWatchEventKinds.OVERFLOW) {
continue; // If events are lost or discarded
}
WatchEvent<Path> watchEvent = (WatchEvent<Path>)event;
//Process files....
}
} catch (InterruptedException e) {
e.printStackTrace();
return;
} finally {
if (key != null) {
boolean valid = key.reset();
if (!valid) break; // If the key is no longer valid, the directory is inaccessible so exit the loop.
}
}
}
}
}
Might help if you specified what server you're using, but have you considered implementing a JMX based service ? It's a bit more "neutral" than EJB, is more appropriate for a background service and has fewer restrictions.
I have a link on my app UI that launches a URL using System.Diagnostics.Process.Start(). If the user clicks the link several times, it opens several tabs.
Is there a way, maybe a command-line option, to still use the default web browser, but have it just reopen the same tab if the URL is already open? It would be OK if it doesn't work with every possible browser out there, but nice if it at least works with IE, Firefox and Chrome.
I doubt it, but since I didn't see any other questions/answers on this topic, I figured I'd ask.
This is somewhat of a workaround but it might get you started. I have used the System.Diagnostics.Process.ProcessId.
As an example I have used IE, I will explain later why I did this. The code is just "quick and dirty" but I just made it as proof of concept.
I have created a basic WinForm app with one button that will open google in IE, if it has already been opened by the application it will not be opened again.
I added the System.Diagnostics reference.
public int ProcessID;
public Form1()
{
InitializeComponent();
}
private void MyButton_Click(object sender, EventArgs e)
{
if (ProcessID == null)
{
StartIE();
}
else
{
if (!ProcessIsRunning())
{
StartIE();
}
}
}
private bool ProcessIsRunning()
{
bool ProcessRunning = false;
foreach (Process p in Process.GetProcesses())
{
try
{
if (p.Id == ProcessID)
{
ProcessRunning = true;
}
}
catch { }
}
return ProcessRunning;
}
private void StartIE()
{
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo.FileName = "iexplore.exe";
proc.StartInfo.Arguments = "http://www.google.be";
proc.Start();
ProcessID = proc.Id;
}
This does not completely do what you requested but it might be a good start. There are a few reasons why I did it this way and what possible options are..
If you would use the url as the Filename, it would indeed open up the webpage in the default browser, it would however not return a processID. This is why the snippet shows usage of IE. (If you would use this option, you could use the System.IO.File.Exists to make sure the desired browser is installed)
If you would like to use this option, you can query the registry to pick up what te default browser is, if you have that you could launch that from the value obtained from the registry. If you then change the process.startinfo.filename to this value, then you will launch the default browser but you will still obtain a processId so this might be the way forward. You can check how to do this over here: http://social.msdn.microsoft.com/Forums/en/netfxbcl/thread/b200903e-ce69-4bd4-a436-3e20a7632dc4
Showing the internet window if it would already be opened, can be done by using the SetForegroundWindow property. As this is already documented in this article, I did not add it in this snippet.
I hope this helps to get you on your way.
I have a console application which can also open winform under certain conditions.Processing(its a database export utility) and be done either through form or commandline. but the form is always associated with command prompt. i mean when i close the console the form get closed as well.My requirement is that when form is launched , the command prompt is closed by itself without closing the form.
[STAThread]
public static void Main(string[] args)
{
if(hastolaunchform)
{
Application.Run(new Form1());
}
else
{
Console.WriteLine("started");
try
{
dataclass.extract();
console.writeline("finish");
}
catch (Exception e)
{
Console.WriteLine("An error occur");
}
}
}
What you have here is an app that has a gui or not.
What you need is a gui version of it that optionally can be run from the CLI, ie it needs to be another exe, or the same exe with different command line parameters, though be careful with that, otherwise it could just keep launching another version of itself until windows dies.
At least I think that's what you are asking.
CLI arguments
MyApp.Exe --GUI
--GUI will apears in args[1].
So something like
if (args.Contains["--GUI"])
{
Application.Run(new Form1());
}
else
{
if (hastolaunchForm)
{
// use Process.start to run another version of your app with --GUI parameter
// and close
}
else
{
// do console stuff.
}
}
}
As part of my App's startup procedure, it checks data integrity, and if it finds a problem it pops up a message to the user telling them that it might take a while to repair things.
I'm showing the message using MessageBox.Show. Because the data check is done from a worker thread, I'm switching over to the UI thread to make that call, and then setting a ManualResetEvent to tell the worker thread when the user has acknowledged the message.
I kick off the data check/load very early in the app's lifecycle from the constructor in the main Application class, by spinning off a worker thread (using the ThreadPool).
When I run with the debugger, and the message is displayed, the app just waits for input. When I run without the debugger, the app terminates after displaying the dialog for 10 seconds.
That 10 seconds is a big clue - it tells me that the OS thinks the app took too long to initialize (the OS kills apps that take too long to start up).
I think that my MessageBox.Show is blocking the UI thread before the App.RootFrameNavigating has a chance to be invoked.
My questions:
Does my diagnosis sound right?
I'd prefer to kick off my data load early, because it is almost entirely IO, except for this Message Box, and the sooner I can get my Model loaded, the better, but do you normally delay your data load until later in the app lifecycle?
Any other ideas/suggestions? I can't guarantee which page will be the start page, because the app could be resuming to any page. I'm also thinking of having the MessageBox.Show delay itself until the app has initialized, perhaps polling away for a flag set by App.RootFrameNavigating - does that make sense?
I think your problem is a result of kicking off the worker thread in the Application constructor. You should use the appropriate life-cycle event, in this case: PhoneApplicationService.Activated Event
So, the solution I've come up with is to still kick off the data load in a worker-thread from the Application's constructor, but in my PhoneService's class ShowDialog method that I invoke to invoke MessageBox.Show, I check to see if the initial navigation has occurred:
private readonly ManualResetEvent _appInitialized = new ManualResetEvent(false);
public void AppInitialized()
{
_appInitialized.Set();
}
public void ShowDialog(string caption, string text, Action<MessageBoxResult> callback, MessageBoxButton button = MessageBoxButton.OKCancel)
{
_appInitialized.WaitOne();
DispatcherHelper.CheckBeginInvokeOnUI(() =>
{
var result = MessageBox.Show(text, caption, button);
if (callback != null)
{
callback(result);
}
});
}
Then in my Application class:
private bool _firstNavigate = true;
private void RootFrameNavigating(object sender, NavigatingCancelEventArgs e)
{
if (_firstNavigate)
{
_firstNavigate = false;
var navigationService = (NavigationService) sender;
navigationService.Navigated += NavigationServiceNavigated;
}
....
private void NavigationServiceNavigated(object sender, NavigationEventArgs e)
{
var navigationService = (NavigationService)sender;
navigationService.Navigated -= NavigationServiceNavigated;
PhoneServices.Current.AppInitialized();
}
Anyone see any issues with this approach? Anyone come up with a better way?