Using the camera in CrossMobile - mobile

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);
// ....
}

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

How to let the user readjust and crop the image as in viber and fb app

How can I let users re-adjust and crop the image as in viber or fb app so that the image uploaded are proportionally scaled to the size we wanted.
Code:
profileImg.addActionListener((e) -> {
Display.getInstance().openGallery(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
try {
if (evt == null) {
// System.out.println("user cancelled");
return;
}
profileImgpath = (String) evt.getSource();
Image i = Image.createImage(profileImgpath);
Image profileImgg = i.scaledWidth(Display.getInstance().getDisplayWidth() / 3);
profileImg.getParent().revalidate();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}, Display.GALLERY_IMAGE);
});
You would need to build your own component to do that. After you retrieve the image from the gallery, you would display the image in your widget, which would allow users to do pinch zoom, and move the photo, etc...
I don't have an example on hand to do this, as it's a pretty specific component you need to build. There is lots of documentation in the CN1 website and developer guide on building custom components, and handling user interaction (e.g. pressing, dragging, etc...).

CefSharp: Injecting custom CSS File using a custom scheme

I'm using CefSharp (47) to render a webpage from a host that I have no control over, and I want to make some additional CSS tweaks to those provided by the host.
Reading up on various topics across GitHub (https://github.com/cefsharp/CefSharp/blob/cefsharp/47/CefSharp.Example/CefSharpSchemeHandlerFactory.cs), and here (CefSharp custom SchemeHandler), I wrote a custom scheme handler accordingly:
public class CustomSchemeHandlerFactory : ISchemeHandlerFactory
{
public const string SchemeName = "custom";
public IResourceHandler Create(IBrowser browser, IFrame frame, string schemeName, IRequest request)
{
Console.WriteLine(request.Url);
if (schemeName.ToLower() == SchemeName.ToLower())
{
// Do some stuff
}
return null;
}
}
I attempt to bind it in my application in the following manner:
CefSettings settings = new CefSettings();
settings.CachePath = browserCachePath;
settings.RegisterScheme(new CefCustomScheme()
{
SchemeName = CustomSchemeHandlerFactory.SchemeName,
SchemeHandlerFactory = new CustomSchemeHandlerFactory()
});
Cef.Initialize(settings);
The application then browses to the appropriate website, and uses the 'LoadingStateChanged' event to then fire off some JavaScript to inject the CSS file I want to load:
string linkText = "<link rel=\u0022stylesheet\u0022 type=\u0022text/css\u0022 href=\u0022custom://custom.css\u0022>";
var jsFunctionText = string.Format("(function() {{ $('head').append('{0}'); return true;}}) ();", linkText);
var injectionTask = await _myBrowser.GetMainFrame().EvaluateScriptAsync(jsFunctionText, null);
...which succeeds.
But my custom resource handler 'Create' event is never fired.
I can only presume that the handler isn't being registered properly, so I'd appreciate any advice/help in getting this working properly!
Thanks!

Implement download progress bar

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

Soundcloud mobile auth with Google+ returns a blank page?

I'm having issues with trying to sign in via Google on the SoundCloud authorize page (www.soundcloud.com/connect). When a user tries to auth with that, they see a blank page and they are not redirected back to the app. It works fine for the Facebook sign in and regular user/pass sign in.
If you are using WebView the problem is it doesn't support popup windows, and they are required by the auth flow. Got it to work by implementing popup support along the lines of https://stackoverflow.com/a/8022295.
private void setUpWebView() {
webView = new WebView(getContext());
webView.setWebChromeClient(new MyChromeClient());
final WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
webSettings.setSupportMultipleWindows(true);
webView.loadUrl(url);
}
...
final class MyChromeClient extends WebChromeClient {
// Add new webview in same window
#Override
public boolean onCreateWindow(WebView view, boolean dialog,
boolean userGesture, Message resultMsg) {
WebView childView = new WebView(getContext());
childView.getSettings().setJavaScriptEnabled(true);
childView.setWebChromeClient(this);
childView.setLayoutParams(FILL);
mContent.addView(childView);
WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
transport.setWebView(childView);
resultMsg.sendToTarget();
return true;
}
// remove new added webview whenever onCloseWindow gets called for new webview.
#Override
public void onCloseWindow(WebView window) {
mContent.removeViewAt(mContent.getChildCount() - 1);
}
}

Resources