I noticed when I use a FileChooser class in order to get an image, it works on Android but not on iOS.
I suppose it might be happening because of different work of filepath or special permissions for iOS.
Any ideas/suggestions?
Thank you.
Here is my code:
ActionListener callback = e -> {
if (e != null && e.getSource() != null) {
String filePath = (String) e.getSource();
cont.removeAll();
try {
Image originImg = Image.createImage(filePath);
Image smallImg = originImg.scaled(getWidth()/2, -1);
ScaleImageButton iv = new ScaleImageButton(smallImg);
iv.addActionListener(evt->{
Dialog previewForm = new Dialog();
previewForm.addPointerReleasedListener(i-> previewForm.dispose());
ImageViewer imagePreview = new ImageViewer();
imagePreview.addPointerReleasedListener(i-> previewForm.dispose());
imagePreview.setImage(originImg.scaled(getWidth(), -1));
previewForm.setDisposeWhenPointerOutOfBounds(true);
previewForm.add(imagePreview);
previewForm.show();
});
cont.add(iv);
revalidate();
} catch (IOException ex) {
}
}
};
if (FileChooser.isAvailable()) {
Log.p("FileChooser open");
FileChooser.showOpenDialog(".png,image/png,.jpg,image/jpg,.jpeg", callback);
} else {
Display.getInstance().openGallery(callback, Display.GALLERY_IMAGE);
}
If you're using the FileChooser cn1lib notice you need to make changes to the provisioning profile. See this: https://github.com/shannah/cn1-filechooser/wiki/iOS-Setup
Related
I want to have a simple form that shows a video from a public URL. So I found out the MediaPlayer controller and I copied the example from the docs
final Form hi = new Form("MediaPlayer", new BorderLayout());
hi.setToolbar(new Toolbar());
Style s = UIManager.getInstance().getComponentStyle("Title");
FontImage icon =
FontImage.createMaterial(FontImage.MATERIAL_VIDEO_LIBRARY, s);
hi.getToolbar().addCommandToRightBar(new Command("", icon) {
#Override
public void actionPerformed(ActionEvent evt) {
Display.getInstance().openGallery((e) -> {
if(e != null && e.getSource() != null) {
String file = (String)e.getSource();
try {
Media video = MediaManager.createMedia(file, true);
hi.removeAll();
hi.add(BorderLayout.CENTER, new MediaPlayer(video));
hi.revalidate();
} catch(IOException err) {
Log.e(err);
}
}
}, Display.GALLERY_VIDEO);
}
});
hi.show();
It worked flawlessly in the simulator, the button appears and when I select a video file the component appears.
But when testing it on actual Android device, after I select the video nothing happens. I wonder if I missed some configuration. I am looking for the simplest possible way to run videos on Codename One for Android.
EDIT: It looks like the event listener in Display#openGallery is not being called.
I am creating a mobile app where I need users to be able to select multiple images. I am using the cn1 lib file chooser but I am only able to select one Image. How can I select multiple images. Here is the code I use to select the image.
chooseImage.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
animateImage.show();
if (FileChooser.isAvailable()){
FileChooser.showOpenDialog(".jpg,.png,.gif", e2->{
String file = (String)e2.getSource();
if (file == null){
animateImage.add("No File Was Selected");
animateImage.revalidate();
}else {
String extension = null;
if (file.lastIndexOf(".") > 0){
extension = file.substring(file.lastIndexOf(".")+1);
}
if ("txt".equals(extension)){
FileSystemStorage fs = FileSystemStorage.getInstance();
try {
InputStream fis = fs.openInputStream(file);
animateImage.addComponent(new SpanLabel(Util.readToString(fis)));
} catch (Exception ex) {
Log.e(ex);
}
}else{
try{
Image image = URLImage.createImage((String)e2.getSource());
animateImage.add(image);
}catch (IOException e){
e.printStackTrace();
}
//animateImage.add("Selected file "+file);
}
}
animateImage.revalidate();
});
/*try{
Image image = URLImage.createImage((String)evt.getSource());
animateImage.add(image);
}catch (IOException e){
e.printStackTrace();
}*/
}
}
});
Thanks
There is no support for that in the cn1lib. You can fork the cn1lib and add support for it manually by changing the native code in the lib.
This isn't supported currently in the standard Codename One API, there is an RFE to add it here: https://github.com/codenameone/CodenameOne/issues/2383
Okay, I don't believe this is a cn1 issue, but I am running out of options. I have an app and I have been using the Capture.capturePhoto to give the user the ability to snap a photo with their device and upload it to my server. Has been working great for several months now. I have been asked to add the ability to upload a photo from the mobiles photo gallery, I thought it would be trivial, but after figuring out how to scale the image down and store it in Storage, I am now stumped with it just sending 0 bytes to my server.
I know it's not my server, that has not changed and can still upload files from various sources including the ones captured with the photo in the cn1 app.
Here is the code that uploads the photo
private void uploadImage(String filename, String name) throws IOException {
String ext = filename.substring(filename.lastIndexOf('.') + 1).toLowerCase();
if (ext.equals("jpg") || ext.equals("jpeg") || ext.equals("pjpeg") || ext.equals("png")) {
MultipartRequest request = new MultipartRequest() {
Hashtable h;
#Override
protected void readResponse(InputStream input) throws IOException {
JSONParser p = new JSONParser();
h = p.parse(new InputStreamReader(input));
super.readResponse(input);
}
#Override
protected void postResponse() {
List<Map<String, Object>> media = (List<Map<String, Object>>)h.get("media");
Dialog.show("Photo Uploaded", media.size() + " photo(s) uploaded and available to send.", "OK", null);
}
};
request.setUrl(MyApplication.IMGSERVER);
request.setPost(true);
request.addData(name, filename, "image/" + ext);
request.addRequestHeader("X-Dart-Token", token);
NetworkManager.getInstance().addToQueue(request);
} else {
Dialog.show("Invalid Photo Format", "The photo format (" + ext+ ") is not supported. Try with jpg or png.", "OK", null);
}
}
Here is the relevant parts of code that get and scale the photo from the gallery
Display.getInstance().openGallery(new ActionListener() {
#Override
public void actionPerformed(ActionEvent actionEvent) {
if (actionEvent != null && actionEvent.getSource() != null) {
String filepath = (String)actionEvent.getSource();
if (filepath != null) {
// scale down the image
String filename = "tempfile.png";
boolean success = false;
if (Storage.isInitialized()) {
try {
OutputStream out = Storage.getInstance().createOutputStream(filename);
ImageIO.getImageIO().save(filepath, out, ImageIO.FORMAT_PNG, 500, -1, 1);
out.close();
success = true;
} catch (IOException e1) {
Log.p("image scaling failed " + e1.getMessage());
Dialog.show("Photo Upload", "Unable to scale photo:" + e1.getMessage(), "OK", null);
}
if (success) {
// open dialog and have user provide name
try {
String tmpFilepath = FileSystemStorage.getInstance().getAppHomePath() + filename;
Dialog.show("Image File", tmpFilepath, "OK", null);
uploadImage(tmpFilepath, name);
} catch (IOException err) {
Log.p("Image Upload Failed:" + err.getMessage());
Dialog.show("Picture Uploaded Failed", "Something prevented the upload of the image.", "OK", null);
}
}
}
}
}
}
I purposely cut out a lot of the surrounding code in the above snippet to focus on what I believe to be important.
I left in the Dialog statements that I am using for debugging so I can see what the path is on the device. If I run this in the simulator, and choose a file, it uploads fine, but when I run it on an iPhone, the file sent to the server has 0 bytes, and the Dialog in the uploadImage method will display that '0 photo(s) uploaded'. When using Storage.g.entrySize() on "tempfile.png" it displays the file has not being 0 in size. How can I properly reference this file to send it to the server.
You are saving the gallery image to Storage but the upload method works with FileSystemStorage those aren't compatible so you get incompatible behaviors.
I have a couple of questions regarding image viewer.
1)ImageViewer autoslides isnot working.The imageViewer works initially when the app is first started. But as soon as any other form is opened & then going back to the form containing imageViewer, the autoslide doesnt work.
Code for img viewer auto slide
placeholderForTable = (EncodedImage) theme.getImage("placeholderWithAnimate.png");
placeholderForTable = placeholderForTable.scaledEncoded(screenWidth, 30 + (screenWidth * 1 / 3));
BusinessForumImagesConnection bfic = new BusinessForumImagesConnection();
bfic.businessForumImagesConnectionMethod(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
DefaultListModel<Image> images;
if (bfic.response != null) {
for (Map<String, Object> entrySet : bfic.response) {
String imgUrl = (String) entrySet.get("imgUrl");
Image adImage = URLImage.createToStorage(placeholderForTable, imgUrl.substring(0, imgUrl.lastIndexOf(".")), + imgUrl, URLImage.RESIZE_SCALE);
adsSlideImagesArray.add(adImage);
}
}
ImageViewer imv = new ImageViewer();
Container adsContainer = BoxLayout.encloseY(imv);
if (adsSlideImagesArray != null) {
slideIndex = 0;
images = new DefaultListModel<>(adsSlideImagesArray);
imv.setImage(images.getItemAt(0));
imv.setImageList(images);
imv.setSwipePlaceholder(Image.createImage(100, 100));
Runnable r = new Runnable() {
public void run() {
if (slideIndex < images.getSize()) {
nextImage = (Image) images.getItemAt(slideIndex);
if (nextImage != null) {
imv.setImage(nextImage);
}
slideIndex++;
} else {
slideIndex = 0;
}
}
};
if (uITimer == null) {
uITimer = new UITimer(r);
}
if (uITimer != null) {
uITimer.schedule(5000, true, f); //5 seconds
}
}
});
2) Some random images are not always displayed in image viewer. It happens in both simulator & real devices. I have checked if the UrlImage is cached or not in storage. There are all the file saved but some of them are never displayed in image viewer.
Instead of image Viewer, i set the image icon in label and loop them. All the labels have their respective icons, but there is a problem in imageViewer. Code is same as above.
Make sure your timer fires and that no one canceled it.
Do you see the placeholder instead of the image? Details like that are essential.
Images that are deeper within the image viewer stack won't be pre-fetched. Notice that URLImage wasn't designed for the image viewer and is probably a bad idea for it as URLImage resizes the images. We recommend using a download method to get full sized images for the image viewer see this old post: https://www.codenameone.com/blog/image-viewer-from-the-web.html
I am trying to write a file browser in CN1 to let the user select a profile picture for upload.
I tried using the FileSystemStorage's isDirectory() method, but it is returning false for a directory.
Code:
private void displayFiles(final Container c, String root)
{
c.removeAll();
FileSystemStorage fs = FileSystemStorage.getInstance();
try {
String files[] = fs.listFiles(root);
for(final String file: files)
{
System.out.println(file+"-->"+fs.isDirectory(file));
if(fs.isDirectory(file))
{
Button b = new Button("Folder::"+file);
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
displayFiles(c, file);
}
});
c.addComponent(b);
}else
{
Container c1 = new Container(new BoxLayout(BoxLayout.X_AXIS));
Label l = new Label("File::"+file);
CheckBox cb = new CheckBox();
c1.addComponent(l);
c1.addComponent(cb);
c.addComponent(c1);
}
}
} catch (IOException ex) {
}
c.revalidate();
}
Output:
CN1Log__$-->false
CN1Preferences-->false
Cookies-->false
data-->false
FaceBookAccesstmp652635968-->false
folder1-->false
folder2-->false
HELLOCN1FS-->false
myFileName-->false
token-->false
Screenshot of the emulator:
Screenshot of the explorer
The behavior is same on the phone as well
Could this be a bug ?
Is there something that I am not doing correctly ?
Thanks
You need to use the full path for the file:
if(fs.isDirectory(root + file))