Implement download progress bar - codenameone

While downloading a file, it shows download progress in the notification or somewhere.
But i think it is not by default in cn1 app. I want to add progress listener. How to make it work??
if (!FileSystemStorage.getInstance().exists(filename)) {
com.codename1.io.Util.downloadUrlToFile(PdfUrl, filename, true);
}

In my case used the code below.
/**
* Adaptation of Util.downloadUrlTo
*/
private boolean downloadUrlToAdapt(String url, final String fileName, boolean storage, final Slider slider) {
final ConnectionRequest cr = new ConnectionRequest();
cr.setPost(false);
cr.setFailSilently(true);
cr.setUrl(url);
if (storage) {
cr.setDestinationStorage(fileName);
} else {
cr.setDestinationFile(fileName);
}
NetworkManager.getInstance().addProgressListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if (evt instanceof NetworkEvent) {
NetworkEvent e = (NetworkEvent) evt;
if (e.getProgressPercentage() >= 0) {
slider.setText(e.getProgressPercentage() + "%");
slider.setProgress(e.getProgressPercentage());
}
}
}
});
NetworkManager.getInstance().addToQueueAndWait(cr);
return cr.getResponseCode() == 200;
}
I needed to show video download progress. I hope it helps.

The way the browser downloads a file locally is a special case for browsers and unrelated to apps. You can just invoke Display.execute with a file and the browser will download it that way although I'm guessing its not what you want since it will not be accessible to you after the fact.
You can show progress using NetworkManager's progress listener. Showing the progress in the notification area is an Android specific behavior and uncommon on iOS. But you might be able to use some of the local notification features https://www.codenameone.com/blog/local-notifications.html

I used it the same way as Sadart Abukari.
Only thing I changed is I used the ToastBar.Status instead to display the progress
[...]
NetworkManager.getInstance().addProgressListener((evt) -> {
if (evt instanceof NetworkEvent) {
NetworkEvent e = (NetworkEvent) evt;
if (e.getProgressPercentage() >= 0) {
status.setProgress(e.getProgressPercentage());
}
}
});
NetworkManager.getInstance().addToQueueAndWait(cr);
//Clear the ToastBar
status.clear();
return cr.getResponseCode() == 200;
}

Related

Paypal Selenium automation Accept Cookies not working

It looks like paypal has updated their plugin lately and my code stopped working. I tried using Selenium IDE but when I record using it I do not see the Accept Cookie modal popup. I am able to get pass login as below, but I tried many different way to get to submit payment button with no luck. Help appreciated.
public IDictionary<string, object> vars { get; private set; }
vars = new Dictionary<string, object>();
_driver.SwitchTo().Frame(0);
vars["WindowHandles"] = _driver.WindowHandles;
_driver.FindElement(By.CssSelector(".paypal-button")).Click();
vars["win8061"] = waitForWindow(2000);
vars["root"] = _driver.CurrentWindowHandle;
_driver.SwitchTo().Window(vars["win8061"].ToString());
_driver.FindElement(By.Id("email")).SendKeys(paypalEmail);
_driver.FindElement(By.Id("btnNext")).Click();
_driver.FindElement(By.Id("password")).SendKeys(paypalPassword);
_driver.FindElement(By.Id("btnLogin")).Click();
//The problem is here!!!
var element = _driver.FindElement(By.Id("payment-submit-btn"));
Actions builder = new Actions(_driver);
builder.MoveToElement(element).Perform();
public string waitForWindow(int timeout)
{
try
{
Thread.Sleep(timeout);
}
catch (Exception e)
{
Console.WriteLine("{0} Exception caught.", e);
}
var whNow = ((IReadOnlyCollection<object>)_driver.WindowHandles).ToList();
var whThen = ((IReadOnlyCollection<object>)vars["WindowHandles"]).ToList();
if (whNow.Count > whThen.Count)
{
return whNow.Except(whThen).First().ToString();
}
else
{
return whNow.First().ToString();
}
}
Had same issue recently after PayPal made some kind of changes to their "Pay" button. All of the sudden it stopped working. Below is what worked for me. There is no logic behind it, besides "just because it works".
After PayPal login; in your case after:
_driver.FindElement(By.Id("btnLogin")).Click();
Use:
Thread.Sleep(1000);
_driver.FindElement(By.Id("acceptAllButton")).Click();
try
{
_driver.FindElement(By.Id("payment-submit-btn")).Click();
}
catch
{
_driver.FindElement(By.Id("payment-submit-btn")).Click();
}

Using the camera in CrossMobile

I am using CrossMobile to create an app and I want to use the camera to capture and save photos from my app. I will also need to access the photos taken from the app to show them in a list. How can I present the camera view on a button press?
First of all you might need the CoreImage Plugin, or else some specific permissions will not be available.
Under iOS you also need to add the NSCameraUsageDescription key in the Info.plist by hand, (or else the application will crash due to Apple's limitation).
Let's assume that you have a UIButton with name cameraButton and an UIImageView with name imgV, both initialized in the loadView section of your code.
Then the core would be similar to:
public void loadView() {
// ....
cameraButton.addTarget((sender, event) -> {
if (!UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera))
new UIAlertView(null, "Unable to access camera", null, "Accept").show();
else {
UIImagePickerController picker = new UIImagePickerController();
picker.setSourceType(UIImagePickerControllerSourceType.Camera);
picker.setDelegate(new UIImagePickerControllerDelegate() {
#Override
public void didFinishPickingMediaWithInfo(UIImagePickerController picker, Map<String, Object> info) {
picker.dismissModalViewControllerAnimated(true);
UIImage img = (UIImage) info.get(UIImagePickerController.OriginalImage);
imgV.setImage(img);
}
#Override
public void didCancel(UIImagePickerController picker) {
picker.dismissModalViewControllerAnimated(true);
}
});
presentModalViewController(picker, true);
}
}, UIControlEvents.TouchUpInside);
// ....
}

captureAudio example in codenameone not working on device simulator

I am trying the captureAudio example given in the codenameone documentation https://gist.githubusercontent.com/codenameone/a347dc9dcadaa759d0cb/raw/089f171a37e43f558ce897a0b51cab46219c37c0/CaptureAudioSample.java
Copying the code here for convenience:
Form hi = new Form("Capture", BoxLayout.y());
hi.setToolbar(new Toolbar());
Style s = UIManager.getInstance().getComponentStyle("Title");
FontImage icon = FontImage.createMaterial(FontImage.MATERIAL_MIC, s);
FileSystemStorage fs = FileSystemStorage.getInstance();
String recordingsDir = fs.getAppHomePath() + "recordings/";
fs.mkdir(recordingsDir);
try {
for(String file : fs.listFiles(recordingsDir)) {
MultiButton mb = new MultiButton(file.substring(file.lastIndexOf("/") + 1));
mb.addActionListener((e) -> {
try {
Media m = MediaManager.createMedia(recordingsDir + file, false);
m.play();
} catch(IOException err) {
Log.e(err);
}
});
hi.add(mb);
}
hi.getToolbar().addCommandToRightBar("", icon, (ev) -> {
try {
String file = Capture.captureAudio();
if(file != null) {
SimpleDateFormat sd = new SimpleDateFormat("yyyy-MMM-dd-kk-mm");
String fileName =sd.format(new Date());
String filePath = recordingsDir + fileName;
Util.copy(fs.openInputStream(file), fs.openOutputStream(filePath));
MultiButton mb = new MultiButton(fileName);
mb.addActionListener((e) -> {
try {
Media m = MediaManager.createMedia(filePath, false);
m.play();
} catch(IOException err) {
Log.e(err);
}
});
hi.add(mb);
hi.revalidate();
}
} catch(IOException err) {
Log.e(err);
}
});
} catch(IOException err) {
Log.e(err);
}
hi.show();
I am using Intellij and trying to test the above code in device simulator. But when I click the mic button I see a 'file chooser' dialog box with only a cancel option enabled. On clicking cancel nothing happens. If I choose a wav file then click ok, it gets copied and i am able to play it in simulator. Is mic input not supported in simulator? Is it getting replaced with file input? Or am I doing anything wrong?
We don't capture from the mic in the simulator as we consider the file chooser more convenient for debugging and simulating actual capture cases. This allows us to reproduce failures/test cases with 100% accuracy.
Also the media API's in JavaSE are "flaky" and we don't want to rely on them anymore than we have to.
On the device you will get a recorder interface as usual.
Notice that this is true for image, video capture and picking from the picture gallery too.

How do I make sure the UI is updated during long running processes in a WPF application?

In a WPF app that follows the MVVM pattern, I've run across a common issue where a user clicks on a button which fires an event in the ViewModel. This event should enable a "Please Wait" spinner animation, do some processing which may take a few seconds, then hide the spinner. I'm not really sure of a good pattern I can use to make sure the spinner animation always appears.
As an example, I have a login process which does the following:
Displays spinner (set property on VM to true, spinner is bound to it)
Attempt to connect to server (can take a few seconds depending on connection)
On a failure, display a failure message
On success, save off some info about the user so it's available to the rest of the app.
What I'm finding is that the spinner never actually appears. I have tried wrapping the longer-running process in a Task.Run call, but that hasn't seemed to help.
Here's an approximation of what the code looks like:
// When true, spinner should be visible
protected bool _authenticatingIsVisible = false;
public bool AuthenticatingIsVisible
{
get { return _authenticatingIsVisible; }
set
{
_authenticatingIsVisible = value;
NotifyOfPropertyChange(() => AuthenticatingIsVisible);
}
}
public void Login()
{
try
{
AuthenticationIsVisible = true;
AuthCode result = AuthCode.NoAuthenticated;
Task.Run(() => { result = _client.Authenticate() }).Wait();
AuthenticationIsVisible = false;
if (result == AuthCode.Authenticated)
{
// Bit of misc. code to set up the environment
// Another check to see if something has failed
// If it has, displays a dialog.
// ex.
var error = new Error("Something Failed", "Details Here", Answer.Ok);
var vm = new DialogViewModel() { Dialog = error };
_win.ShowDialog(vm);
return;
}
else
{
DisplayAuthMessage(result);
}
}
finally
{
AuthenticationIsVisible = false;
}
}
The proper way would be not to block the UI thread (which is what you are doing right now with .Wait()), and use AsyncAwait instead.
private Task<AuthCode> Authenticate()
{
return Task.Run<AuthCode>(()=>
{
return _client.Authenticate();
});
}
public async void Login()
{
AuthenticationIsVisible = true;
AuthCode result = await Authenticate();
AuthenticationIsVisible = false;
}

CodeName One IOS CaptureAudio

I called captureAudio method from Capture class.
It opens an empty dialog box on IOS 7, with save/cancel buttons.
No audio bar shown to user understands recording.
It's ok on android.
Since iOS doesn't have a capture UI like Androids this is implemented entirely in Java. You can write your own implementation of this rather easily e.g. this is from the Codename One IOSImplementation.java file that does exactly that:
public void captureAudio(ActionListener response) {
String p = FileSystemStorage.getInstance().getAppHomePath();
if(!p.endsWith("/")) {
p += "/";
}
try {
final Media media = MediaManager.createMediaRecorder(p + "cn1TempAudioFile", MediaManager.getAvailableRecordingMimeTypes()[0]);
media.play();
boolean b = Dialog.show("Recording", "", "Save", "Cancel");
final Dialog d = new Dialog("Recording");
media.pause();
media.cleanup();
d.dispose();
if(b) {
response.actionPerformed(new ActionEvent(p + "cn1TempAudioFile"));
} else {
FileSystemStorage.getInstance().delete(p + "cn1TempAudioFile");
response.actionPerformed(null);
}
} catch(IOException err) {
err.printStackTrace();
response.actionPerformed(null);
}
}

Resources