I have a j2me midlet running on a cell phone. The code works fine, but the issue that comes up is that the program seems to be running more than one instance of itself. I have code at the beginning of the application inside the appStart() method that runs twice when the application starts. During the lifetime of the program, the code can be seen running twice when text is written to the screen.
The code looks like this:
public MyClass()
{
form = new Form("MyProgram");
cmdClose = new Command("EXIT", Command.EXIT, 1);
form.addCommand(cmdClose);
form.setCommandListener(this);
display = Display.getDisplay(this);
display.setCurrent(form);
}
public void startApp()
{
form.append("App starting\n");
// Rest of program
}
I have no idea why the code is being called twice.
I'm coding on the i290.
This is definitely a JVM bug. startApp() should be called only once at startup and can't be called again until pauseApp() is called or you call notifyPaused() yourself.
What I suggest is the following code:
private boolean midletStarted = false;
public void startApp() {
if (!midletStarted) {
midletStarted = true;
//Your code
}
}
This way you can track midlet state changes. But in fact it is better that you don't use this method at all and use constructor instead.
Oh, by the way, I don't think that there are some multiple instances or something like that, this is merely a JVM error.
Maybe you did something that made the runtime call pauseApp() and then when you set the focus to the app the runtime called startApp() again.
Put logging in pauseApp() and see what happens.
Related
I've been developing with codenameone for over a year, and I never ran into this problem before, I feel like I'm losing my mind. I just redesigned one part of an app I'm working on, and now the ActionListeners aren't firing. I'm attaching them to a Button and a SpanButton in the code:
ActionListener goToDoc = new ActionListener() {
String mDocId = docId;
#Override
public void actionPerformed(ActionEvent evt) {
mStateMachine.currentExpertId = mDocId;
mStateMachine.showForm("DoctorDetails", null);
}
};
name.addActionListener(goToDoc);
Util.downloadImageToStorage(mStateMachine.URL_PREFIX+"images/doctors/"+(String)value.get("doc_pic"),
"doc_post_pic_"+(String)value.get("doc_id")+".png", new Callback<Image>() {
#Override
public void onSucess(Image img) {
pic.setIcon(img.scaledWidth(mStateMachine.getProportionalWidth(.23)));
StateMachine.applyGreenBorder(pic);
pic.addActionListener(goToDoc);
pic.getParent().revalidate();
}
#Override
public void onError(Object sender, Throwable err, int errorCode, String errorMessage) {
System.out.println("Unable to download expert profile picture");
}
});
When I debug the code, the components do show that the ActionListener is attached, but the actionPerformed method is never reached, no matter how many times I click on the buttons. I experience this problem both on the simulator and on an Android device. I have yet to test on an iPhone.
Did you set a parent to be a lead component or focusable?
The reason the click event wasn't firing was because the Components weren't enabled, possibly a bug in the BUI Builder. After checking off the 'Enabled' and 'Focusable' checkboxes in the GUI Builder, and seeing they were unchecked every time I went back to that form, I just used component.setFocusable(true) and component.setEnabled(true) in the code, and it worked fine after that.
I've created a java library (named: invoke) with a java class (Invoke). Its seen when expanding Script libraries under code in the designer navigation pane.
The code is:
package com.kkm.vijay;
public class Invoke {
public static void main(String[] args) {
Runtime r = Runtime.getRuntime();
Process p = r.exec("C://some.exe");
}
}
Used the following ssjs to an onclick event of a button shows Error:500 when previewed in browser.
importPackage(com.kkmsoft.vijay);
var v=new Invoke();
v.main();
Even i used a function inside the class and changed the last line of ssjs to v.fn(). Yet the same problem.
There are a number of things wrong, and as Fredrik mentions you should switch on the standard Error page.
Your first code won't run because it is not correctly capturing the Exception. You are also using a main() method, which is normally used to execute a program. But you are calling it without any arguments. Avoid using that method unless it is for executing an application.
So change it to this:
package com.kkm.vijay;
import java.io.IOException;
public class Invoke {
public void mainCode() {
Runtime r = Runtime.getRuntime();
try {
Process p = r.exec("C://WINDOWS//notepad.exe");
} catch (IOException e) {
e.printStackTrace();
}
}
}
You should put that code in the new Java view in Designer.
Next your button code needs to change.
var v=new com.kkm.vijay.Invoke();
v.mainCode();
Testing that it should work fine. The issue next is, as it is SSJS the application will execute on the server. There may be security implications in this, and it may need you to modify the java.policy file in order to do this.
The related permission will be java.io.FilePermission.
I've been reading about AsyncTasks and Hanlders and Loopers but I still can't figure out where I'm going wrong in my code. I'm trying to run code that will look over a Tic Tac Toe grid and determine the best move for the computer. I want this code to run in the background 'cause it can take some time and then I can update the UI level with a textbox that says something like "I'm Thinking". I've tried this a bunch of different ways, none with success.
private class PostTask extends AsyncTask<String, Integer, String> {
private Board _b;
private Welcome.Player _opp;
private int _depth;
#Override
protected void onPreExecute() {
super.onPreExecute();
}
protected void SetVars(Board b, Player p, int depth){
_b = b;
_opp = p;
_depth = depth;
}
#Override
protected String doInBackground(String... params) {
Looper.prepare();
try{
_bestMove = _b.GetBestMove(_opp,_depth);
}
catch(Exception err){
_bestMove = -1;
}
return "All done";
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if(_bestMove == -1){
TextView tv = (TextView) findViewById(R.id.tv_Score);
tv.setText("Had and error, couldn't make a move.");
}
FollowUpComputerMove(this);
}
The above code will work for exactly 5 moves and then it crashes. When I watch in the debugger I see new theads being created named Thread<#> AsyncTask #1. Once I get to five of those AsyncTasks it goes back to try and grab the first AsyncTask and crashes. When it crashes I'm shown the ThreadPoolExecutor.class file.
I've also read that I shouldn't be using both the AsyncTask and the Looper objects together so I've tried taking the Loooper.prepare() statement out, but then my AsyncTask fails immediately with the error message:
Can't create handler inside thread that has not called Looper.prepare() - AsyncTask inside a dialog
I've read repeatedly that you shouldn't be trying to update the UI from an AsyncTask and that often the above error is because of that, but GetBestMove isn't updating the UI thread. When I trace through to see where the error comes, it fails when calling a constructor saying it can't find the class.
Can anyone point me in the right direction? My end goal is to use one main thread and only one background thread, and just keep re-using the background thread whenever the computer needs to make a move. I know that the recursive method GetBestMove works when I run this program in a single-thread manner. But the screen freezes for too long on some moves as the method is being run. Thank you so much.
-NifflerX
Apologies for answering my own question, but the issue I was facing had nothing to do with recursion. The class I was calling was extending the class Activity, and while trying to call that from an AsyncTask the program was erroring out. When I removed the extends Activity from the class definition it started working again. Sorry for the post.
-NifflerX
Questions about threads are in no shortage, I know, but I can't seem to find a "full" example of a thread doing http work and then coming back to update the UI.
I basically call a few web services upon app launch. I obviously don't want to freeze the UI so I would want to use a separate thread, right? I have found a bunch of examples online on how to get a new thread to perform some task. But I haven't yet found one that shows how to actually update the UI when the thread's task is done.
How do I know when the web service thread is done? Is there a callback method? Can I access the UI from this callback method if one exists.
Edit: (Here is some code)
//The activate method is called whenever my application gains focus.
public void activate(){
DoSomething wsThread = new DoSomething();
wsThread.start();
}
public void wsCallBack()
{
myTabScreen.add(new ButtonField("Callback called"));
}
public class DoSomething extends Thread
{
public void run()
{
try
{
wsCallBack();
}
catch(Exception e)
{
}
}
}
Very simple. But it never creates the button.
Any ideas?
Thanks a lot.
You can set up a "callback" system to notify the UI when the threads complete. Have a class that extends Thread and pass to it a reference of the class that should be called at the end. If you have a list of such classes that needs to be notified create a Vector on the Thread implementation to hold them. Override the run function and after doing everything you need to do simply call a method on the UI class (iterating through the vector if needed). So your classes may look like:
public class commThread extends Thread{
MyUIClass callbackObj;
public commThread(MyUIClass myUiClass){
callbackObj = myUiClass;
}
public void run(){
//do stuff
callbackObj.callback();
}
}
and your UI class:
public MyUIClass{
public void callback(){
//refresh the UI
}
}
Of course if you have multiple threads running at the same time and calling the same UI object make sure to synchronize the callback method.
Hope this helps!
In a multi form .NetCF 3.5 application I'm trying create the forms in the background while the user is occupied with the previous form.
We're using Orientation Aware Control in the project
We use a wrapper class (FormController) (please let me know if I'm using the wrong terminology) to keep static references to the different forms in our application. Since we only want to create them once.
At the moment the Forms are created the first time they are used. But since this is a time consuming operation we'd like to do this in the background while the user
Application.Run(new FormController.StartUI());
class FormController{
private static object lockObj = new object();
private static bool secIsLoaded = false;
private static StartForm startForm = new StartForm();
private static SecForm m_SecForm;
static SecForm FormWorkOrderList
{
get
{
CreateSecForm();
return m_SecForm;
}
}
private static void StartUI(){
startForm.Show();
ThreadStart tsSecForm = CreateSecForm;
Thread trSecForm = new Thread(tsSecForm);
trSecForm.Priority = ThreadPriority.BelowNormal;
trSecForm.IsBackground = true;
trSecForm.Start();
return startForm;
}
private static void CreateSecForm()
{
Monitor.Enter(lockObj);
if(!secIsLoaded){
m_SecForm = new SecForm();
secIsLoaded = true;
}
Monitor.Exit(lockObj);
}
private static void GotoSecForm()
{
SecForm.Show();
StartForm.Hide();
}
When I call GotoSecForm() the program throws an excepton on SecForm.Show() with an exection with hResult: 2146233067 and no other valuable information.
The stacktrace of the exception is:
on Microsoft.AGL.Common.MISC.HandleAr(PAL_ERROR ar)
on System.Windows.Forms.Control.SuspendLayout()
on b..ctor(OrientationAwareControl control)
on Clarius.UI.OrientationAwareControl.ApplyResources(CultureInfo cultureInfo, Boolean skipThis)
on Clarius.UI.OrientationAwareControl.ApplyResources()
on Clarius.UI.OrientationAwareControl.OnLoad(EventArgs e)
on Clarius.UI.OrientationAwareControl.c(Object , EventArgs )
on System.Windows.Forms.Form.OnLoad(EventArgs e)
on System.Windows.Forms.Form._SetVisibleNotify(Boolean fVis)
on System.Windows.Forms.Control.set_Visible(Boolean value)
on System.Windows.Forms.Control.Show()
I'm quite qlueless about what's going wrong here. Can anyone help me out?
Or are there some better ways to load the forms in the background?
Let me know if any more information is needed.
You can't create forms (or safely do any manipulation of controls or forms) in background threads. They need to be created on the same thread that the message pump is running on - its just the way that Windows Forms work.
Creating the form itself shouldn't be in itself an expensive task. My advice would be to perform any expensive computations needed to display the form in a background thread, and then pass the result of those computations back to the main message pump in order to create and display the form itself.
(Half way through writing this I realised that this question is about windows mobile, however I'm 99% sure that the above still applies in this situation)