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?
Related
I am new to android development so I think this may be a teething issue on my part, but I am currently trying to use the PixelCopy function in android studio. I have code as shown below, and it matches what the base class is expecting although it is returning an error. Would anyone be able to assist me with this issue?
The code I currently have is as follows:
final HandlerThread handlerThread = new HandlerThread("PixelCopier");
handlerThread.start();
SurfaceView current = new SurfaceView(view.getContext());
PixelCopy.OnPixelCopyFinishedListener copyResult;
// Make the request to copy.
PixelCopy.request(current, bitmap, copyResult, handlerThread);
if (copyResult. == PixelCopy.SUCCESS) {
//If successful do tasks in here
}
Try crating extracting finish listener as shown below in class.
private static void onPixelCopyFinished(int result) {
if (result != PixelCopy.SUCCESS) {
Log.e("err", "errMsg");
return;
}
}
You can pass the listener as below and also you'll also need to wrap it in try catch as it might throw an exception.
try {
PixelCopy.request(current, bitmap, <YOUR CLASS>::onPixelCopyFinished, this.getHandler());
} catch (IllegalArgumentException e) {
// PixelCopy may throw IllegalArgumentException, make sure to handle it
e.printStackTrace();
}
so, here is my today problem:
First of all, please note that I do NOT have the Matlab parallel toolbox available.
I am running java code witch interact with Matlab. Sometime Matlab directly call some java functions, sometimes it is the opposite. In this case, we use a notification system which comes from here:
http://undocumentedmatlab.com/blog/matlab-callbacks-for-java-events
We then address the notification in proper callbacks.
Here is a simple use case:
My user select a configuration file using the java interface, loaded into Matlab.
Using an interface listener, we notify Matlab that the configuration file has been selected, it then run a certain number of functions that will analyzes the file
Once the analysis is done, it is pushed into the java runtime, which will populate interface tables with the result. This step involve that matlab will call a java function.
Finally, java request the interface to be switched to an arbitrary decided tab.
This is the order of which things would happen in an ideal world, however, here is the code of the listener actionPerformed method:
#Override
public void actionPerformed(ActionEvent arg0) {
Model wModel = controller.getModel();
Window wWindow = controller.getWindow();
MatlabStructure wStructure = new MatlabStructure();
if(null != wModel) {
wModel.readMatlabData(wStructure);
wModel.notifyMatlab(wStructure, MatlabAction.UpdateCircuit);
}
if(null != wWindow) {
wWindow.getTabContainer().setSelectedComponent(wWindow.getInfosPannel());
}
}
What happen here, is that, when the notifyMatlab method is called, the code does not wait for it to be completed before it continues. So what happen is that the method complete and switch to an empty interface page (setSelectedComponent), and then the component is filled with values.
What I would like to, is for java to wait that my notifyMatlab returns a "I have completed !!" signal, and then pursue. Which involves asynchrounous code since Matlab will code java methods during its execution too ...
So far here is what I tried:
In the MatlabEventObject class, I added an isAcknowledge member, so now the class (which I originaly found in the above link), look like this (I removed all unchanged code from the original class):
public class MatlabEventObject extends java.util.EventObject {
private static final long serialVersionUID = 1L;
private boolean isAcknowledged = false;
public void onNotificationReceived() {
if (source instanceof MatlabEvent) {
System.out.println("Catched a MatlabEvent Pokemon !");
MatlabEvent wSource = (MatlabEvent) source;
wSource.onNotificationReceived();
}
}
public boolean isAcknowledged() {
return isAcknowledged;
}
public void acknowledge() {
isAcknowledged = true;
}
}
In the MatlabEvent class, I have added a future task which goal is to wait for acknowledgement, the methods now look like this:
public class MatlabEvent {
private Vector<IMatlabListener> data = new Vector<IMatlabListener>();
private Vector<MatlabEventObject> matlabEvents = new Vector<MatlabEventObject>();
public void notifyMatlab(final Object obj, final MatlabAction action) {
final Vector<IMatlabListener> dataCopy;
matlabEvents.clear();
synchronized (this) {
dataCopy = new Vector<IMatlabListener>(data);
}
for (int i = 0; i < dataCopy.size(); i++) {
matlabEvents.add(new MatlabEventObject(this, obj, action));
((IMatlabListener) dataCopy.elementAt(i)).testEvent(matlabEvents.get(i));
}
}
public void onNotificationReceived() {
ExecutorService service = Executors.newSingleThreadExecutor();
long timeout = 15;
System.out.println("Executing runnable.");
Runnable r = new Runnable() {
#Override
public void run() {
waitForAcknowledgement(matlabEvents);
}
};
try {
Future<?> task = service.submit(r);
task.get(timeout, TimeUnit.SECONDS);
System.out.println("Notification acknowledged.");
} catch (Exception e) {
e.printStackTrace();
}
}
private void waitForAcknowledgement(final Vector<MatlabEventObject> matlabEvents) {
boolean allEventsAcknowledged = false;
while(!allEventsAcknowledged) {
allEventsAcknowledged = true;
for(MatlabEventObject eventObject : matlabEvents) {
if(!eventObject.isAcknowledged()) {
allEventsAcknowledged = false;
}
break;
}
}
}
}
What happen is that I discover that Matlab actually WAIT for the java code to be completed. So my waitForAcknowledgement method always wait until it timeouts.
In addition, I must say that I have very little knowledge in parallel computing, but I think our java is single thread, so having java waiting for matlab code to complete while matlab is issuing calls to java functions may be an issue. But I can't be sure : ]
If you have any idea on how to solve this issue in a robust way, it will be much much appreciated.
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'm using Retrofit2 and DBFlow. I have a problem when I save my data into my database. Certain data are duplicated when I'm calling the thread twice at the same time. The problem is my List because this variable is final. And I have to set final because I need to use this List in my thread.
Then, there is a way to remove the final to my List and replace by something ?
Retrofit onResponse()
public void onResponse(Call<AdminPictures> call, Response<AdminPictures> response) {
AdminPictures apResponse = response.body();
// Here is my list
final List<PictureInfos> pictureInfos = apResponse.getPicturesList();
new Thread(new Runnable() {
#Override
public void run() {
try {
// The List is used here
for (PictureInfos infos : pictureInfos) {
if(!infos.exists()){
infos.save();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
move the declaration of the list to the top of the class and make a class variable...
List<PictureInfos> pictureInfos....
Make it a class variable.
Otherwise, instead of anonymous class; move your code into a separate class. Then pass the variable using constructor
Please try this
synchronized(this) {
for (PictureInfos infos : pictureInfos) {
if(!infos.exists()){
infos.save();
}
}}
What I'm trying, is to first let insert a thread data, meanwhile block another.
Maybe you have request twice and response twice,so thread is excuted twice.
Maybe this is silly, but have you tried clearing the variable at the end of the for cycle?
...
for (PictureInfos infos : pictureInfos) {
if(!infos.exists()) {
infos.save();
}
}
pictureInfos.clear();
...
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.