Android Java: "Cannot resolve" in postDelayed - java

I am using the first answer here to try to initiate a repeating task, updating a seekbar ("timeSlider") to show progress as an audio file plays. The repeating function is updateTimeSlider(). When initiated via postDelayed, updateTimeSlider gives a "cannot resolve symbol" error (see image at the bottom of this post). updateTimeSlider() does not give that error when on a line by itself (also shown in the image).
(Note that updateTimeSlider() on the line by itself is not really how the code will go. It's just there to demonstrate that it works in that position.)
Can anyone help me understand how to correct the problem in the postDelayed line?
Several people have suggested that I just forgot to write the do in doUpdateTimeSlider. I did not forget. I wanted to execute updateTimeSlider (without the do), which does execute just fine and does not produce an error outside of postDelayed. updateTimeSlider is a C++ function used via JNI (Java Native Interface) using a statement at the bottom of this Java file that looks like this:
private native void updateTimeSlider();
The JNI aspect of things is working fine, and updateTimeSlider() is the method I am trying to execute, not doUpdateTimeSlider.
As an aside, I did try putting doUpdateTimeSlider in there, and it also results in an error: Variable doUpdateTimeSlider may not have been initialized.
I also don't see what good it would do me if I could execute doUpdateTimeSlider since there is no code in it to actually update the the timeSlider seekbar.
public class PlayActivity extends AppCompatActivity {
private static final String TAG = "PlayActivity";
boolean playing = false;
private int timeSliderInterval = 1000; // 1 second
private Handler timeSliderHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_play);
final Runnable doUpdateTimeSlider = new Runnable() {
#Override
public void run() {
timeSliderHandler.postDelayed(updateTimeSlider, timeSliderInterval);
updateTimeSlider();
}
};

You could replace:
timeSliderHandler.postDelayed(updateTimeSlider, timeSliderInterval);
with:
timeSliderHandler.postDelayed(doUpdateTimeSlider, timeSliderInterval);
You forgot to write do in doUpdateTimeSlider.

As you can see here : https://stackoverflow.com/a/41413191/4409113
It is : doUpdateTimeSlider
final Runnable doUpdateTimeSlider = new Runnable() {
#Override
public void run() {
timeSliderHandler.postDelayed(doUpdateTimeSlider, timeSliderInterval);
updateTimeSlider();
}
};
Which #ρяσѕρєя K said the same.
Update:
To fix that may not have been initialized you can follow these links:
variable r might not have been initialized
"Variable example might not have been initialized" in anonymous class
So:
final Runnable etc = null;
final Runnable doUpdateTimeSlider = new Runnable() {
#Override
public void run() {
timeSliderHandler.postDelayed(etc, timeSliderInterval);
updateTimeSlider();
}
};
This should work now!

Related

How to Access Activity from ActivityScenarioRule

I am using ActivityScenarioRule for Espresso UI Testing and I wanted to get access to the method getStringArray(), calling which requires the Activity . So, is there any way to retrieve the Activity by the ActivityScenarioRule , maybe something similar to getActivity in ActivityTestRule.
#Rule
public ActivityScenarioRule activityScenarioRule = new ActivityScenarioRule<>(MainActivity.class);
I am not using ActivityTestRule, because it is deprecated!
Since it appears you're using Java, here's how you'd do it:
#Rule
ActivityScenarioRule<MainActivity> activityScenarioRule = new ActivityScenarioRule<>(MainActivity.class);
#Test
public void test() {
activityScenarioRule.getScenario().onActivity(activity -> {
// use 'activity'.
});
}
Please read the documentation for more info on these new ways of interacting with the activity under test.
For anyone who wants Activity, but that without need to re-write all tests to run on UI-thread, a fairly straightforward Java way to get it:
Waiting for UI
Assume you want to test if a dialog is shown after some delay, the onActivity(...) hook runs on UI-thread, which means waiting in there would cause the dialog to be nerver shown.
In such cases you need to keep a strong-reference to ActivityScenario (as that prevents Activity close).
Test should wait for onActivity(...) hook to be called, then keep passed Activity's reference.
Finally, move test logic out of onActivity(...) hook.
Example
private ActivityScenario mActivityScenario;
#After
public void tearDown() throws Exception {
if (mActivityScenario != null) {
mActivityScenario.close();
}
mActivityScenario = null;
}
#Override
public Activity getActivity() {
if (mActivityScenario == null) {
mActivityScenario = ActivityScenario.launch(getActivityClassForScenario());
}
return tryAcquireScenarioActivity(mActivityScenario);
}
protected static Activity tryAcquireScenarioActivity(ActivityScenario activityScenario) {
Semaphore activityResource = new Semaphore(0);
Activity[] scenarioActivity = new Activity[1];
activityScenario.onActivity(activity -> {
scenarioActivity[0] = activity;
activityResource.release();
});
try {
activityResource.tryAcquire(15000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
Assert.fail("Failed to acquire activity scenario semaphore");
}
Assert.assertNotNull("Scenario Activity should be non-null", scenarioActivity[0]);
return scenarioActivity[0];
}
Espresso states the following:
At the same time, the framework prevents direct access to activities
and views of the application because holding on to these objects and
operating on them off the UI thread is a major source of test
flakiness.
When there is no other way I use the following method to get an arbitrary activity from an ActivityScenarioRule. It uses onActivity mentioned in the accepted answer:
private <T extends Activity> T getActivity(ActivityScenarioRule<T> activityScenarioRule) {
AtomicReference<T> activityRef = new AtomicReference<>();
activityScenarioRule.getScenario().onActivity(activityRef::set);
return activityRef.get();
}
Any onView(...) code inside onActivity led to a timeout in my testcases. So, I extracted the activity and used it with success outside the onActivity. Beware tho! See the statement above.
#Test
fun checkForUpdate() {
val scenario = ActivityScenario.launch(MainActivity::class.java)
scenario.onActivity {
UpdateTool.checkForUpdate(it)
}
}

Reset AsyncTask to multiple execution

Is there any way to use AsyncTask.execute() multiple times?
Im using AsyncTask to check, if User exist in my Room Database.
My Login.class looks like this:
public class Login extends AsyncTask<String, Boolean, Boolean> {
public Login(Context context, LoginListener listener){
db = ApplicationDatabase.getDatabase(context); //i get Room here
this.context = context; //context of app
this.listener = listener; //my interfece for observe Boolean, works ok
}
#Override
protected Boolean doInBackground(String... body){
try {
user = db.userDao().getUser(body[0], body[1]);
if (user != null)
return Boolean.TRUE; //we find user with credentials
else {
return Boolean.FALSE; //we not find user with that credentials (from body)
}
}
catch(Exception e){
return null;
}
}
protected void onPostExecute(Boolean result) {
listener.onLoginPerformed(result); //Boolen to activity
selfRestart(); //i want to restart task here
}
private void selfRestart(){
//maybe something to do here? its my own method
}
private ApplicationDatabase db;
private User user;
private LoginListener listener;
private Context context;
I call Task in this way (my Activity.class):
login = new Login(getApplicationContext(), this);
//this is an interface that i implements in Activity definition
loginButton.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
//execute() here, i cuted some not necesery code from here
try {
// im using get because i want to get valu from AsyncTask
login.execute(email, password).get();
}
catch(Exception e){ }
}
I Read, that we can reset AsyncTask by making new AsyncTask (Task = new Login()) StackOverflow Thread but it dont work for me. When i try to make something like this in my Login class:
private void selfRestart(){
Login task = new Login(context, listener);
task.execute("");
//im calling it in onPostExecute()
}
My android app crashes. My question is, what is the best way to reset AsyncTask that is implemented in diffrent file then my Activity class? Or maybe there is better way to make Login activity than implemented whole logic for login in AsyncTask?
EDIT:
Logcat:
2019-01-24 15:45:31.407 1048-1048/com.example.admin.keystroke_dynamics E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.admin.keystroke_dynamics, PID: 1048
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.Boolean.booleanValue()' on a null object reference
at com.example.admin.keystroke_dynamics.Activities.LoginActivity.onLoginPerformed(LoginActivity.java:62)
at com.example.admin.keystroke_dynamics.Login.onPostExecute(Login.java:38)
at com.example.admin.keystroke_dynamics.Login.onPostExecute(Login.java:14)
at android.os.AsyncTask.finish(AsyncTask.java:692)
at android.os.AsyncTask.-wrap1(AsyncTask.java)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:709)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:156)
at android.app.ActivityThread.main(ActivityThread.java:6523)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:942)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:832)
You say,
I call Task in this way (my Activity.class):
login = new Login(getApplicationContext(), this);
//this is an interface that i implements in Activity definition
loginButton.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
//execute() here, i cuted some not necesery code from here
try {
// im using get because i want to get valu from AsyncTask
login.execute(email, password).get();
}
catch(Exception e){ }
}
, but no, you are not "calling" your task that way. You are creating a single instance of the task, and setting up an event handler that executes that task -- that specific instance -- whenever the loginButton is clicked. Since each AsyncTask instance may be executed only once, that will fail the second time the login button is clicked (if not sooner, for some other reason).
You also say,
I Read, that we can reset AsyncTask by making new AsyncTask (Task = new Login())
, but no, that does not reset anything, and indeed AsyncTask objects cannot be reset. The advice you read was to replace the used AsyncTask with a fresh instance. Instantiating a new AsyncTask has no particular effect on others. If you want to pursue that approach then it might look something like this:
loginButton.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
Login myLoginTask = login; // keep a reference to the current task
login = new Login(... arguments ...); // create a new task for the next click
try {
// use the original task
myLoginTask.execute(email, password).get();
}
catch(Exception e){ }
}
That specific implementation requires login to be non-final, so probably an instance variable of the containing class, not a local variable of the method from which your code was excerpted.
HOWEVER, your best way forward might very well be to ditch AsyncTask altogether. When you use it like this:
login.execute(email, password).get();
... you defeat the entire purpose. You are making the thread in which that runs block until the task completes (that's what AsyncTask::get is for), so the task is effectively synchronous. If that's what you require then you should just do the wanted work more directly instead of wrapping it up in an AsyncTask.

Minecraft Plugin scheduleSyncDelayedTask Error

I have a problem and am new at making Minecraft plugins and writing code in general.
I am trying to make a plugin that waits about 15 seconds before executing the second command however the code I have now has an error when I try to do (plugin, new Runnable(). I have done some research and it most people say that is because I don't have this in my Main class. The problem is that I don't want it in my Main. So I was wondering what I have to do to make this work.
Code below. Thanks in advance for any help you can provide.
~Stone
#Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if (sender instanceof Player){
//checks to see if player sent command
Player player = (Player) sender;
if (args.length >= 1) {
//too many arguments message
player.sendMessage(Utils.chat("&4There were too many arguments, I could not complete that command"));
}
if (player.hasPermission("reloadc.use")) {
//reloads server, sends message, and stores variable value
Bukkit.broadcastMessage(Utils.chat("&6Server will be reloaded in 15 seconds by &5" + player.getDisplayName()));
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
public void run() {
Bukkit.broadcastMessage(Utils.chat("&6This works"));
}
}, 20L);
Bukkit.broadcastMessage(Utils.chat("&6IT WORKED!!!!!"));
}
else if (!player.hasPermission("reloadc.use")) {
player.sendMessage(Utils.chat("&4You do not have permission to reload the server"));
player.sendMessage(Utils.chat("&5If you belive this is a mistake please contact an admin"));
}
}
return true;
}
}
The Code that is giving me problems is right here (the word plugin)
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
public void run() {
Bukkit.broadcastMessage(Utils.chat("&6This works"));
}
}, 20L);
Here are 3 images with the errors that it is giving me. The only change that i did not make was the getServer(). because it gave me more errors and did not change anything for the better at least from what I can tell.
1[]2
[]
Ok So I have completed the changes, everything says that it works but now when I run the command that I setup it does everything it should except wait for 15 seconds. It executes the text one after the other telling me that it will be reloaded in 15 seconds and then at the same time it tells me it worked. Nothing seems wrong to me now, it just says that it is running fine and my wait time is 300L which is server ticks. That should equal 15.
Images of completed code below.
In response to your update/edit:
Your error happens because you use plugin does not mean anything to your code. You need to declare it as a variable before you use in there, or assuming that you wrote all the code in one class for your plugin then you can easily replace plugin with this like so Bukkit.getScheduler().scheduleSyncDelayedTask(this, new Runnable() {.
If it is in another class then to declare the variable you need to pass it in from another class or call it from your Main plugin class. The following will show you haw to pass it to your listener class.
In your main plugin class you need to do this, note how we add this to the function that is calling your command class new CommandClass(this) note that your class will have a different name than CommandClass:
public class Main extends JavaPlugin{
#Override
public void onEnable(){
new CommandClass(this);
}
}
And then in the command class, we modify it to receive the variable public CommandClass(Main plugin):
public class CommandClass implements CommandExecutor{
private Main plugin;
public CommandClass(Main plugin){
this.plugin = plugin;
}
}
Now your onCommand method will work because you have a reference to plugin in your class:
#Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
Bukkit.getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
#Override
public void run() {
Bukkit.broadcastMessage(Utils.chat("&6This works"));
}
}, 300L);
}
Original answer edited a little to include some of the response to your screenshots:
I can see four problems:
Your error happens because you have not referenced your actual plugin, but just typed plugin.
Please note that the delay is in server ticks, so 20L will only have
a delay of 1 second. If you want 15 seconds delay then use 300L.
You didn't use the #Override annotation, but it is very important for the runnable task.
You could use getServer().getScheduler() instead of Bukkit.getScheduler(), just in case there is something funky going on with your code and you have managed to start more than one instance of the server.
Here is an updated version of your code with 1 and 3 fixed:
Bukkit.getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
#Override
public void run() {
Bukkit.broadcastMessage(Utils.chat("&6This works"));
}
}, 300L);
Here is an updated version of your code with suggestion 4 included:
getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
#Override
public void run() {
Bukkit.broadcastMessage(Utils.chat("&6This works"));
}
}, 300L);

Matlab & Java: Execute matlab asynchronously

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.

GWT - Methods in onModuleLoad() called multiple times

I'm trying to write a simple application to display chart data. I want to display some data as soon as the user loads the page, so I'm getting data & drawing tables inside of the Runnable as described in the gwt-visualization Getting Started.
Things seem to work alright, except charts tend to get loaded more than once. Below is my onModuleLoad().
private final StatisticsServiceAsync statisticsService = GWT.create(StatisticsService.class);
GWTBeanFactory factory = GWT.create(GWTBeanFactory.class);
DataTable locationData;
AnnotatedTimeLine atl;
GeoMap usMap;
TextBox storeField;
Button log10Button;
DateRange durationChartRange;
String eusrJson = null;
Button b;
HTML last1000Html;
public void onModuleLoad() {
storeField = new TextBox();
storeField.setText("Enter a store");
storeField.addKeyDownHandler(new MyKeyHandler());
b = new Button("Get Stats!");
log10Button = new Button("Show Log10 Scale");
log10Button.addClickHandler(new Log10ClickHandler());
b.addClickHandler(new MyClickHandler());
last1000Html = new HTML();
getLast1000Avg();
Runnable onLoadCallback = new Runnable() {
public void run() {
storeDurationData = DataTable.create();
storeDurationDataLog10 = DataTable.create();
RootPanel.get("storeDurationDiv").add(storeField);
RootPanel.get("storeDurationDiv").add(b);
RootPanel.get("storeDurationDiv").add(log10Button);
RootPanel.get("storeDurationDiv").add(last1000Html);
log10Button.setVisible(false);
// Get initial Data
getAvgByRegion();
getLast1000Avg();
Scheduler.get().scheduleFixedDelay(new RepeatingCommand() {
#Override
public boolean execute() {
getLast1000Avg();
return true;
}
}, 5000);
}
};
// Load the visualization api, passing the onLoadCallback to be called
// when loading is done.
VisualizationUtils.loadVisualizationApi(onLoadCallback, AnnotatedTimeLine.PACKAGE);
VisualizationUtils.loadVisualizationApi(onLoadCallback, GeoMap.PACKAGE);
}
All of the "simple" elements seem to get populated correctly, as the Button, HTML, and TextBox all get placed appropriately (which used to be inside of run, they're where they are now as a result of debugging previous errors). However, the GeoMap gets placed twice, and looking at the logging you can tell that the Runnable's run is being executed at least twice, which seems reasonable, but I don't know how to keep it from adding twice.
I'm probably screwing up something with the Async stuff, but I'm new and confused. Below is my getAvgByRegion() method:
private void getAvgByRegion() {
statisticsService.getEusrForRegion(new AsyncCallback<String>() {
#Override
public void onFailure(Throwable caught) {
System.out.println(":(");
}
#Override
public void onSuccess(String result) {
createLocTable();
DataTable dt = parseEusrLocations(result);
usMap = new GeoMap(dt, createGeoMapOptions());
usMap.setSize("800px", "600px");
RootPanel.get("storeDurationDiv").add(usMap);
}
});
}
Any advice on how best to work with GWT is welcome.
So, you call VisualizationUtils.loadVisualizationApi twice, so the onLoadCallback will be run twice (I don't know GWT Google Apis, this is a supposition).
onLoadCallback calls getAvgByRegion, so that one will get called twice too; and it gets data and in the callback creates a new GeoMap and adds it to the RootPanel.get("storeDurationDiv"), so you get two GeoMaps on the screen.
The other widgets(storeField, etc.) are created only once, so adding them repeatedly is not a problem (except performance-wise), as they'll first be removed from their current parent before being added to the new one (which in this case is the same)

Categories

Resources