Alert Message in external Cordova Android Plugin? - java

I there a way to show a message from android java files in cordova? I've tried alert, log.i, console.log, print and System.out.println, but nothing works. By building the app, an error shows up.
for example:
log.w("test");
error: no suitable method found for w(String)
Only callbackContext works, but sends a success or failed return and the code stops at this point.
EDIT:
System.out hasn't appeared anything, now I try over hours to work with loadUrl but recieve error messages like this one:
error: variable mainView might not have been initialized
Code:
import org.apache.cordova.CordovaWebView;
public class VideoCapture extends CordovaPlugin {
#Override
public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException {
CordovaWebView mainView;
mainView.loadUrl("javascript:alert('hello');");
How do I implement the webView?

If you use System.out, it should appear on the logcat
if you want to execute javascript code from java you can use the loadUrl method, so you can use javascript alert or console.log. Example:
webView.loadUrl("javascript:alert('hello');");
or to run it on the UI Thread
cordova.getActivity().runOnUiThread(new Runnable() {
public void run() {
webView.loadUrl("javascript:alert('hello');");
}
});
or this to run on main thread
cordova.getThreadPool().execute(new Runnable() {
public void run() {
webView.loadUrl("javascript:alert('hello');");
}
});

Related

I can't execute a cordova callback multiple times

I develop an ionic-cordova project. I need execute a cordova callback more than once.
Here is my Component codes:
let data =JSON.parse(JSON.stringify(this.someOptions))
this.customService.TestFunction(data).then(response => {
console.log(response);
})
.catch(ex => {
// console.log(ex)
})
}
Here is my CustomService
TestFunction(arg1: any): Promise<any> {
var temp = cordova(this, "TestFunction", { callbackStyle: "object" }, [arg1]);
return temp
}
Here is js code
exports.TestFunction = function (arg0, success, error) {
exec(success, error, 'SomeCordovaPlugin', 'TestFunction', [arg0]);
};
Here is Java codes for android
public class SomeCordovaPlugin extends CordovaPlugin {
private CallbackContext testCallbackContext;
#Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
if (action.equals("TestFunction")) {
this.TestFunction(args, callbackContext);
return true;
}
return false;
}
private void TestFunction(JSONArray args, CallbackContext callbackContext) {
testCallbackContext=callbackContext;
if (args != null) {
try {
for(int i=0;i\<7;i++){
PluginResult pluginResult = new PluginResult(PluginResult.Status.OK ,testCallbackContext.getCallbackId());
pluginResult.setKeepCallback(true); // keep callback
testCallbackContext.sendPluginResult(pluginResult);
}
} catch (Exception ex) {
testCallbackContext.error("An error occured:" + ex);
}
}
}
}
I want to call cordova exec more than once. pluginResult.setKeepCallback(true) is not work for me. I am using ionic 6 and cordova 11. How can I call cordova exec more than once?
If i understand your problem correctly you have a custom cordova plugin which you call from your js side.
You then want to return results from your plugin to the js world multiple times and not just once.
The problem is that the lifecycle of your plugin invocation is completed by calling sendPluginResult()
I have solved this by not using sendPluginResult() to transfer my return values to JS but calling a JS function directly via the WebView:
1. In JS set a custom function which will be called from your plugin with your result values on the object of your custom plugin like:
cordova.plugins.<pluginPackage>.<CustomPlugin>.<CustomCallbackFunction> = (data) => {
//your JS side processing of data returned from your plugin more than once
}
With your values for and
2. Persisting your callbackContext in your custom Plugin to finally finish the call as you already do by calling sendPluginResult()
3.
Upon invocation of your plugin function dont't call sendPluginResult() but instead directly prompt the webview to process JS code where you call your previously in 1. defined callback Function
webView.sendJavascript("cordova.plugins.<pluginPackage>.<CustomPlugin>.<CustomCallbackFunction>('" + <your payload as JSON string> + "')") (Kotlin code)
4. Finally when you are finished calling your callback multiple times call sendPluginResult() on your persisted callbackContext status OK to finish the plugin invocation.

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);

Android Java: "Cannot resolve" in postDelayed

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!

Android InstrumentTest hangs until minimizing the app

I just started to look into Android instrumentation tests but have some problems with getting my tests executed. Here is what I tried:
Using Android Studio and gradle, I created a simple test class within src/instrumentTest/java/. Here it is:
package at.example.test;
import android.test.ActivityInstrumentationTestCase2;
import android.view.View;
import at.example.activity.MainActivity;
public class BasicAppTestCase extends ActivityInstrumentationTestCase2<MainActivity> {
private MainActivity activity;
public BasicAppTestCase() {
super(MainActivity.class);
}
#Override protected void setUp() throws Exception {
super.setUp();
activity = getActivity();
}
public void testAppHomeButtonExists() {
View homeButton = activity.findViewById(android.R.id.home);
assertNotNull("Home button does not exist", homeButton);
}
}
Next, I start the test using by right clicking on my project and selecting Run 'All Tests'. Android Studio executes assembleDebug and assembleTest tasks for my project, and installs both apk files onto my test device.
Afterwards, the app is successfully started on my test device. The setUp() method is getting executed (I checked this by putting a failing assert into the method as well as using logcat) and then the test execution hangs, showing Running tests... and testAppHomeButtonExists as being currently executed.
The test execution won't proceed until I change the activity state by minimizing the app pressing the home button or opening the app switcher. Then the test method testAppHomeButtonExists gets executed and (depending on the methods body) succeeds or fails. Again, I tested this behavior using assert calls and the logcat output.
UPDATE:
This is what the TestRunner is logging to my device's logcat stream:
11-11 15:34:59.750 24730-24748/at.example.activity I/TestRunner﹕ started: testAppHomeButtonExists(BasicAppTestCase)
Up until I stop the app nothing more is logged. After stopping the activity following is logged:
11-11 15:35:05.205 24730-24748/at.example.activity I/TestRunner﹕ finished: testAppHomeButtonExists(BasicAppTestCase)
11-11 15:35:05.205 24730-24748/at.example.activity I/TestRunner﹕ passed: testAppHomeButtonExists(BasicAppTestCase)
Am I doing something wrong? Am I missing something? What could cause this behavior?
Thanks in advance!
Instead of checking view like that u can try something like this :
public class BasicAppTestCase extends ActivityInstrumentationTestCase2<MainActivity> {
private MainActivity activity;
private Button;
public BasicAppTestCase() {
super(MainActivity.class);
}
#Override protected void setUp() throws Exception {
super.setUp();
activity = getActivity();
button = (Button) activity
.findViewById(android.R.id.home);
}
public final void testPreconditions() {
assertNotNull(activity);
}
public final void testFieldsOnScreen() {
final Window window = tAes_Activity.getWindow();
final View origin = window.getDecorView();
assertOnScreen(origin, button);
}
}
I have found the problem: I created an infinite invalidation loop inside one of my views onDraw() method. A velociraptor should eat me for using old code without checking it first. This is what the view's drawing method looked like:
#Override protected void onDraw(Canvas canvas) {
// Get the current location on screen in pixels (left = 0)
int[] location = new int[2];
this.getLocationOnScreen(location);
// Translate the canvas for the same location as its current offset (resulting in a doubled shift).
canvas.translate(location[0], 0);
// Now draw the translated content.
super.onDraw(canvas);
this.invalidate();
}
The above drawing method created a "faked parallax effect" of the view's content. The problem was, that although this did not result in a ANR it caused the hosting Activity to never go idle causing my test's getActivity() method not to return as it's implementation waits for an idle activity (meaning the setup completed). The question Android animation causing "Activity idle timeout for History Record" on start up is a similar problem. My quick solution was to defer the invalidate() call to the parent ViewPager. Since my parallax effect needed only to be updated when the position of my page changed I am now using a ViewPager.OnPageChangeListener() that updates child views as soon as they move.
This fixes the problem for me! My tests are running now and are fully functional!

Check WebView's URL while Unit Testing in Robotium

Im trying to figure out the easiest way to check my Main Activity's URL inside my (WebView). This is going to be in a Unit Test using the Robotium 4.1 framework. All i am trying to figure out how i can interact with the webview, such as send the activity a URL to load, so i can test against that and make sure the correct URL is loaded and also check my actionbar items as well.
Any Codes, suggestions or recommendations would be highly appreciated.
public class ErrorHandling extends
ActivityInstrumentationTestCase2<Webview_Main> {
private Solo solo;
private WebView web;
..
protected void setUp() throws Exception {
super.setUp();
solo = new Solo(getInstrumentation(),getActivity());
}
Updated per recommendations (Currently - NullPointerException Erorrs)
public void testUrl() {
String URL = solo.getString(com.example.webview.R.string.url);
web = (WebView) getActivity().findViewById(R.id.webview_main); //Added
try {
solo.assertCurrentActivity("Launching Main Activity", Webview_Main.class);
assertTrue(solo.getWebUrl().equals("URL")); }
catch (Error error) {
}
}
public void testWeb() {
try {
web = (WebView) getActivity().findViewById(R.id.webview_main); //Added
solo.getCurrentActivity().runOnUiThread(new Runnable() {
public void run() {
web.loadUrl("http://www.google.com");
}
});
solo.sleep(1000);
} catch (Error error) {
}
}
first, calling
web.getSettings();
gives you nothing. It provides you WebSettings, but you don't do anything with that object.
To assert current url in your webview you can use:
assertTrue(solo.getWebUrl().equals("your url"));
To load specified url in your webview you have to run it in another thread (here I'm not sure, if it should be runOnMainSync or runOnUiThread, however I tried runOnUiThread and it worked fine), for instance:
solo.getCurrentActivity().runOnUiThread(new Runnable() {
public void run() {
web.loadUrl("http://www.OTHER_url_TO_test_AGAINST");
}
});
The steps to check the URL are as follows:
1) Create the webview object for the specific application
obj = (WebView)getActivity().findViewById((package name of source or apk).R.id.(Id of the source webview))
Note: If you dont have the source code of the source application of whome you are writing the test case then use the hierarchy viewer to find the id of the webview.
2) Add some sleep so that it will wait the time taken to load the url
solo.sleep(time)
3) Use this to get the current value or status of the application.
obj.getSettings()
4) Take a Boolean variable and store the value of
Boolean variable = solo.getWebUrl().equals("URL to be tested");
5) assertTrue(Boolean variable)
To verify the value true or false.

Categories

Resources