I'm having problems with a button that fires a timer. If I take away all the if statements it works fine so there is nothing wrong with the timer code. This same code works fine in every other phone I have tried 8900, storm, etc..
It's only on the 9800 that it fails and runs to the end of the if statements.
Is there a change in the getLabel?
My code is:
startbtn.setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field field1, int context) {
/////sound file
try {
Manager.playTone(ToneControl.C4, 100, 50);
} catch (MediaException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (startbtn.getLabel() == "START"){
startbtn.setLabel("STOP!");
startTimer();
} else if (startbtn.getLabel() == "STOP!"){
startbtn.setLabel("RESET");
stopTimer();
} else if (startbtn.getLabel() == "RESET"){
dismiss();
//// RESET SCREEN AFTER
}
}
});
I hope someone can help I can't find an answer anywhere.
I would worry you that correct comparison of strings in Java is str1.equals(str2) and also there is usually precondition str1 != null.
But there is exception in cases similar to yours. Just introduce constants:
private static final String START_LABEL = "START!";
private static final String STOP_LABEL = "STOP!";
private static final String RESET_LABEL = "RESET";
And use constants in if statements. Like this:
if (START_LABEL == startbtn.getLabel()) {}
More about String comparison in Java here and here.
I hope your app requires only English localization. It is more readable to use Camel case notation for variable naming.
Related
I had an issue where Text to Speech would not speak anything. I realised this was due to the fact that I was attempting to call 'Speak()' before TTS had initialised.
I need to wait until TTS has initialised, so that I can call 'Speak()' successfully. I thought doing something along the lines of this would work:
#Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
mTTSInitialised = true;
} else {
Log.e("TTS", "Initialisation Failed!");
}
}
...
while(!mTTSInitialised){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
But this fails to initialise at all. Is there a way to do this effectively?
The initialisation of the Text to Speech engine is asynchronous, which is why you realised you have to 'wait' for it to complete, before requesting that it processes an utterance.
Even when it eventually initialises successfully, it can be subsequently killed by the system, or it can of course fail to initialise, so you always need to be ready to handle a request to speak, where the engine isn't prepared.
Add the following helper class
public class PendingTTS {
private String pendingUtterance;
private int pendingQueueType;
public String getPendingUtterance() {
return this.pendingUtterance;
}
public void setPendingUtterance(#NonNull final String pendingUtterance) {
this.pendingUtterance = pendingUtterance;
}
public int getPendingQueueType() {
return this.pendingQueueType;
}
public void setPendingQueueType(final int pendingQueueType) {
this.pendingQueueType = pendingQueueType;
}
}
Assuming you're using an Activity, you need to declare the following variables:
private volatile PendingTTS pendingTTS;
private static final int MAX_INIT_ATTEMPTS = 4;
private volatile int initCount;
and initialise the Text to Speech object in onCreate()
tts = new TextToSpeech(YOURActivity.this, YOURonInitListener);
In your onInitListener you would check if there is any pending speech:
#Override
public void onInit(final int status) {
switch (status) {
case TextToSpeech.SUCCESS:
initCount = 0;
// Set up tts stuff
tts.setOnUtteranceProgressListener(YOURprogressListener);
if (pendingTTS != null) {
// We have pending speech, process it and check the result
int speechResult = tts.speak(pendingTTS.getPendingUtterance(),pendingTTS.getPendingQueueType(),
// remaining tts variables here)
switch (speechResult){
case TextToSpeech.SUCCESS:
// Result was successful
pendingTTS = null;
break;
case TextToSpeech.ERROR:
// Speech failed
// Check if it has repeatedly failed up to the max attempts
if(initCount < MAX_INIT_ATTEMPTS){
initCount ++;
tts = new TextToSpeech(YOURActivity.this, YOURonInitListener);
} else {
// Totally broken - let the user know it's not working
}
break;
}
} else {
// there was nothing to process
}
break;
case TextToSpeech.ERROR:
// Check if it has repeatedly failed up to the max attempts
if(initCount < MAX_INIT_ATTEMPTS){
initCount ++;
tts = new TextToSpeech(YOURActivity.this, YOURonInitListener);
} else {
// Totally broken - let the user know it's not working
}
break;
}
I've glued the above together from my code - where the speech and initialisation methods are all separated, but I tried to give you an overview above of everything you need to handle.
Elsewhere in your code, when you make a tts.speak(//stuff here) request, you need to check the result as demonstrated above, to make sure it was successful. Again, in my code, this is separated into one single method. If it does fail, you need to set the PendingTTS parameters prior to attempting to initialise again:
pendingTTS = new PendingTTS();
pendingTTS.setPendingQueueType(// your queue type);
pendingTTS.setPendingUtterance(// your utterance);
It is is successful, make sure pendingTTS is set to null.
The overall design is that if the initialisation failed, it will attempt to initialise again, up to the maximum allowed attempts. If the speech fails, it will attempt to initialise the engine again, firstly setting the PendingTTS parameters.
Hope you managed to follow that.
Hmm..
Not a very good idea.
You can try to add the text to the TTS queue and let it do it's work. This snippet can be inside button click, etc as:
tts.speak(toSpeak, TextToSpeech.QUEUE_ADD, null);
Small tutorial that would help.
I have spent almost three days trying to do a simple enable / disable of Actions in the netbeans plaform, something that I though was going to be simple, and should be a common feature is more complex than I thought.
At the begging I tried to see if there was an setEnable() method on the default actions generated and to my surprise there is not. Then I started looking into that and I found that most common method to do it was setting a conditionally enabled action (which depends on a Cookie class), So I figured out how to add a fake class to the Lookup so it gets enabled and disabled, I did it the following way. To test it out I added the following code to another action which should enable or disable the second one.
private final PlottingStarted plottingStarted = new PlottingStarted();
#Override
public void actionPerformed(ActionEvent e) {
// TODO implement action body
if (Lookup.getDefault().lookup(PlottingStarted.class) == null) {
ic.add(plottingStarted);
}else{
ic.remove(plottingStarted);
}
So PlottingStarted is a fake object I created which only purpose is being in the lookup to disable or enable the action.
For some reason it did not do anything at all an the Action was always disabled. I tried many things and finally I gave up.
Then I tried a different approach and was using AbstractActions which do have the setEnabled() ability.
To retrieve the action I based myself on one the Geertjan blogs and I created the following method
public Action findAction(String actionName) {
FileObject myActionsFolder = FileUtil.getConfigFile("Actions/RealTimeViewer");
if (myActionsFolder != null){
FileObject[] myActionsFolderKids = myActionsFolder.getChildren();
for (FileObject fileObject : myActionsFolderKids) {
//Probably want to make this more robust,
//but the point is that here we find a particular Action:
if (fileObject.getName().contains(actionName)) {
try {
DataObject dob = DataObject.find(fileObject);
InstanceCookie ic = dob.getLookup().lookup(InstanceCookie.class);
if (ic != null) {
Object instance = ic.instanceCreate();
if (instance instanceof Action) {
Action a = (Action) instance;
return a;
}
}
} catch (Exception e) {
ErrorManager.getDefault().notify(ErrorManager.WARNING, e);
return null;
}
}
}
}
return null;
}
This method worked perfectly and I was able to retrieve the action and call its setEnabled() method. Unfortunately no matter why I did the Action was always enabled.
Reading some literature I found that I should add the following to the registration of the action "lazy = false" and finally I was able to enable and disable the Action... But off course the default registration is lost and I have no Icons and Names.
Now I decided to post again because I cannot believe that it need to be that complex, there must be a way to do it easier. The only thing I need is to have a PLAY / STOP functionality, when PLAY is enabled STOP is disabled and vice-versa.
I have not done this myself but it seems to be covered in Chapter 5.1.2.1 "Complex Enablement" of the book "Netbeans Platform for Beginners". https://leanpub.com/nbp4beginners
The book is not free but the corresponding code sample is available on
github. https://github.com/walternyland/nbp4beginners/tree/master/chapters/ch05/5.1.2.1 He extends AbstractAction overrides the resultChanged method and uses super.setEnabled().
#ActionID(id = "org.carsales.evaluator.EvaluateCarAction1", category = "Car")
#ActionRegistration(displayName = "not-used", lazy = false)
public class EvaluateCarAction extends AbstractAction
implements ContextAwareAction, LookupListener {
// ...
#Override
public void resultChanged(LookupEvent le) {
//Optionally, check if the property is set to the value you're interested in
//prior to enabling the Action.
super.setEnabled(result.allInstances().size() > 0);
}
Thanks to everybody for your responses. I finally got it to work by extending AbstractAction, it seems that even if you register "lazy = false" some of the registration is still being done by the platform and you just need some minor tweaking in the Action constructor. The final result was
#ActionID(
category = "RealTimeViewer",
id = "main.java.com.graph.actions.StopPlotting"
)
#ActionRegistration(
//iconBase = "main/java/com/graph/images/stop-plotting-24x24.png",
displayName = "#CTL_StopPlotting",
lazy = false
)
#ActionReference(path = "Toolbars/RealTimeViewer", position = 600)
#Messages("CTL_StopPlotting=Stop Plotting")
public final class StopPlotting extends AbstractAction{
private static final String ICON = "main/java/com/dacsys/cna/core/graph/images/stop-plotting-24x24.png";
public StopPlotting() {
putValue(SMALL_ICON, ImageUtilities.loadImageIcon(ICON, false));
putValue(NAME, Bundle.CTL_StopPlotting());
this.setEnabled(false);
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO implement action body
Action a = new ActionsHelper().findAction("StartPlotting");
if (a != null){
if (a != null){
if (a.isEnabled()){
a.setEnabled(false);
this.setEnabled(true);
}else{
a.setEnabled(true);
this.setEnabled(false);
}
}
}
}
}
I'm trying to use OpenGL directly from Java using JNA on Mac OSX (I have done it successfully with Windows and Linux). I've browsed thru JOGL source but they use CALayers which I don't understand yet. I would like to just simply use NSOpenGLView if possible and place it over top the AWT Canvas. I find the NSWindow using JNA and add the NSOpenGLView I created and it seems to work except when I call [nsOpenGLContext setView] or [nsOpenGLView lockFocus] I get an 'invalid drawable' error. I learned from Rococoa how to use ObjectiveC from Java.
Here is some sample code:
private static boolean createMac(GL gl, Component c) {
NSAutoreleasePool pool = new NSAutoreleasePool();
pool.alloc();
pool.init();
gl.nsopenglview = new NSOpenGLView();
gl.nsopenglview.alloc();
Pointer ptr = Native.getWindowPointer(findWindow(c));
NSObject nsComponent = new NSObject();
nsComponent.obj = ptr;
Pointer cClass = nsComponent._class();
NSView view = new NSView();
view.alloc();
boolean isView = view.isKindOfClass(cClass);
// JFLog.log("test=" + isView);
if (isView) {
view.dealloc();
view.obj = ptr; //do NOT dealloc this (usually NSWindowViewAWT)
gl.nswindow = view.window();
} else {
view.dealloc();
gl.nswindow = new NSWindow();
gl.nswindow.obj = ptr;
}
NSOpenGLPixelFormat fmt = new NSOpenGLPixelFormat();
fmt.alloc();
fmt.initWithAttributes(new int[] {
NSOpenGLPFAWindow,
// NSOpenGLPFAAccelerated, //is not available on my test system
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAColorSize,24,
NSOpenGLPFADepthSize,16,
0 //zero terminate list
}
);
if (fmt.obj == null) {
JFLog.log("NSOpenGLPixelFormat initWithAttributes failed");
return false;
}
if (gl.nsopenglview != null) {
gl.nsopenglview.initWithFrame(new NSRect(c.getBounds()), fmt);
}
NSView content = gl.nswindow.contentView();
JFLog.log("content view=" + content.obj);
content.addSubview(gl.nsopenglview);
JFLog.log("layered=" + content.wantsLayer());
//use created context
gl.nsopenglcontext = gl.nsopenglview.openGLContext();
//create some resize/move listeners
final GL _gl = gl;
final Component _c = c;
c.addComponentListener(new ComponentListener() {
public void componentResized(ComponentEvent e) {
_gl.nsopenglview.setFrame(new NSRect(_c.getBounds()));
}
public void componentMoved(ComponentEvent e) {
_gl.nsopenglview.setFrame(new NSRect(_c.getBounds()));
}
public void componentShown(ComponentEvent e) {}
public void componentHidden(ComponentEvent e) {}
});
if (api == null) {
api = new GLFuncs();
gl.glLibrary = NativeLibrary.getInstance("OpenGL");
try {
Field fields[] = api.getClass().getFields();
for(int a=0;a<fields.length;a++) {
String name = fields[a].getName();
try {
fields[a].set(api, gl.glLibrary.getFunction(name));
} catch (Throwable t) {
JFLog.log("OpenGL:Warning:Function not found:" + name);
}
}
} catch (Exception e) {
JFLog.log(e);
}
}
pool.release();
return true;
}
I can't use the drawRect function in NSOpenGLView so I just lockFocus, use gl commands and unlockFocus when done. But the NSOpenGLContext doesn't have a view assigned and trying to assign the one I created generates the 'invalid drawable'.
Any ideas?
If you want a full working demo goto http://javaforce.sf.net and download v7.15.0, run ant in /jf and then in /projects/jtest3d and then execute run.sh (click the GLCanvas test).
I got it working! The problem was in Rococoa (or possibly a bug in JNA). Their NSRect structure does not pass to [NSOpenGLView initWithFrame] or [NSWindow initWithContentRect] properly. If I pass the 4 fields directly (x,y,width,height) to the function instead of the Structure itself then it works. Also I used [NSObject performSelectorOnMainThread] to make sure I do all GUI stuff on the main thread.
So it is possible to use OpenGL using pure JNA from Java. No native code needed.
This should be available in my javaforce.sf.net in v7.16 which I'll release in a while.
Thanks.
I am trying to check to see if a view is displayed with Espresso. Here is some pseudo code to show what I am trying:
if (!Espresso.onView(withId(R.id.someID)).check(doesNotExist()){
// then do something
} else {
// do nothing, or what have you
}
But my problem is .check(doesNotExist()) does not return boolean. It is just an assertion. With UiAutomator I was able to just do something like so:
if (UiAutomator.getbyId(SomeId).exists()){
.....
}
Conditional logic in tests is undesirable. With that in mind, Espresso's API was designed to guide the test author away from it (by being explicit with test actions and assertions).
Having said that, you can still achieve the above by implementing your own ViewAction and capturing the isDisplayed check (inside the perform method) into an AtomicBoolean.
Another less elegant option - catch the exception that gets thrown by failed check:
try {
onView(withText("my button")).check(matches(isDisplayed()));
//view is displayed logic
} catch (NoMatchingViewException e) {
//view not displayed logic
}
Kotlin version with an extension function:
fun ViewInteraction.isDisplayed(): Boolean {
try {
check(matches(ViewMatchers.isDisplayed()))
return true
} catch (e: NoMatchingViewException) {
return false
}
}
if(onView(withText("my button")).isDisplayed()) {
//view is displayed logic
} else {
//view not displayed logic
}
I think to mimic UIAutomator you can do this:
(Though, I suggest rethinking your approach to have no conditions.)
ViewInteraction view = onView(withBlah(...)); // supports .inRoot(...) as well
if (exists(view)) {
view.perform(...);
}
#CheckResult
public static boolean exists(ViewInteraction interaction) {
try {
interaction.perform(new ViewAction() {
#Override public Matcher<View> getConstraints() {
return any(View.class);
}
#Override public String getDescription() {
return "check for existence";
}
#Override public void perform(UiController uiController, View view) {
// no op, if this is run, then the execution will continue after .perform(...)
}
});
return true;
} catch (AmbiguousViewMatcherException ex) {
// if there's any interaction later with the same matcher, that'll fail anyway
return true; // we found more than one
} catch (NoMatchingViewException ex) {
return false;
} catch (NoMatchingRootException ex) {
// optional depending on what you think "exists" means
return false;
}
}
Also exists without branching can be implemented really simple:
onView(withBlah()).check(exists()); // the opposite of doesNotExist()
public static ViewAssertion exists() {
return matches(anything());
}
Though most of the time it's worth checking for matches(isDisplayed()) anyway.
We need that functionality and I ended up implementing it below:
https://github.com/marcosdiez/espresso_clone
if(onView(withText("click OK to Continue")).exists()){
doSomething();
} else {
doSomethingElse();
}
I hope it is useful for you.
You check with the below code also. If view is displayed it will click else it will pass on.
onView(withText("OK")).withFailureHandler(new FailureHandler() {
#Override
public void handle(Throwable error, Matcher<View> viewMatcher){
}
}).check(matches(isDisplayed())).perform(customClick());
Why no one mentioned:
onView(withId(R.id.some_view_id)).check(matches(not(doesNotExist())))
just add not before doesNotExist. But if you use this logic a lot it's better to use a custom matcher.
Based on the answer by Dhiren Mudgil, I ended up writing the following method:
public static boolean viewIsDisplayed(int viewId)
{
final boolean[] isDisplayed = {true};
onView(withId(viewId)).withFailureHandler(new FailureHandler()
{
#Override
public void handle(Throwable error, Matcher<View> viewMatcher)
{
isDisplayed[0] = false;
}
}).check(matches(isDisplayed()));
return isDisplayed[0];
}
I'm using this to help determine which View in a ViewFlipper is currently displayed.
I think that what Espresso wants you to do is to change your logic to use doesNotExist()
I have for example
onView(snackBarMatcher).check(doesNotExist())
onView(withId(R.id.button)).perform(click())
onView(snackBarMatcher).check(matches(isDisplayed()))
It's been some time since this issue was stated, but as it is one of the top hit on Google when searching for ways to make sure a view is present, before doing any actions on it in Espresso, I would like to share my very basic way of handling this.
1: Start out by writing an extension to ViewInteraction:
fun ViewInteraction.exists(): Boolean {
val viewExists = AtomicReference<Boolean>()
this.perform(object : ViewAction {
override fun perform(uiController: UiController?, view: View?) {
viewExists.set(view != null)
}
override fun getConstraints(): Matcher<View>? {
return Matchers.allOf(ViewMatchers.withEffectiveVisibility(
ViewMatchers.Visibility.VISIBLE),
ViewMatchers.isAssignableFrom(View::class.java))
}
override fun getDescription(): String {
return "check if view exists"
}
})
return viewExists.get()
}
2: Create a simple help method in your base class (to be used in all test classes):
fun viewExists(id: Int): Boolean {
return try {
onView(withId(id)).exists()
} catch (e: RuntimeException) {
false
}
}
With this you either get true or false from onView(withId(id)).exists(), or safely catch the RuntimeException and return false.
Normally a simple check to .exists() would be sufficient, but in some cases, like when you are deleting ListView items until non is left -> when the last item is deleted, the ListView might no longer be present, then an Exception is thrown when trying to check if it exists.
3: With the above implementation, it is safe to check if any view exists, since the RuntimeException is handled nicely behind the scene:
if(viewExists(R.id.something)) {
//do something
}
//do something else
I cannot think of a proper way to wait for an object to appear. I am writing a camera app. After taking a picture, I am writing GPS Data into the exif tags. I have to wait for the location object to appear, before writing. My quick and dirty fix is to start a new thread and use a while loop to "wait" for the object:
private static class MyRunnable implements Runnable {
private final String imagePath;
private final String thumbPath;
MyRunnable(final String anImagePath, String aThumbPath) {
this.imagePath = anImagePath;
this.thumbPath = aThumbPath;
}
public void run() {
while (mCurrentLocation == null) {
//do nothing
}
try {
writeExifTags(imagePath);
writeExifTags(thumbPath);
}
catch (NullPointerException e) {
Log.i(TAG, "NullPointerException");
}
}
}
This works but the empty while-loop looks very ugly. I think of some kind of handler for the object but cannot think of a way to use handlers to check for the existence of mCurrentLocation. Anyone with a flash of wit? :) (Yes the try/ catch block is obsolete now ^^)
You could try using an AsyncTask?