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.
Related
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
I've researched different solutions to this problem, but none of them works for me. I am trying to download a file from Firebase (which I am successful in doing) and then I am trying to open that file in my app right after the download completes. However, my app either crashes or does nothing.
Below is the code for downloading the file (from FirebaseStorage which works):
public void download(String name) {
final String pdf_name = name.substring(0, name.lastIndexOf('.'));
storageReference = firebaseStorage.getInstance().getReference();
ref=storageReference.child("Auctions/" + name);
ref.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
String url = uri.toString();
downloadFile(ActiveAuctionsActivity.this, pdf_name, ".pdf", DIRECTORY_DOWNLOADS, url);
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
SpannableString spannableString = new SpannableString("אין תיק עבודה למכרז זה");
spannableString.setSpan(
new ForegroundColorSpan(getResources().getColor(android.R.color.holo_red_light)),
0,
spannableString.length(),
0);
Toast.makeText(ActiveAuctionsActivity.this, spannableString, Toast.LENGTH_LONG).show();
}
});
}
public void downloadFile(Context context, String fileName, String fileExtention, String destinationDirectory, String url){
DownloadManager downloadmanager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
Uri uri = Uri.parse(url);
DownloadManager.Request request = new DownloadManager.Request(uri);
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDescription("מוריד.....");
//request.setDestinationInExternalFilesDir(context, destinationDirectory, fileName + fileExtention);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName + fileExtention);
// call allowScanningByMediaScanner() to allow media scanner to discover your file
request.allowScanningByMediaScanner();
downloadmanager.enqueue(request);
registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
Toast.makeText(getApplicationContext(), "מוריד את התיק העבודה.....",
Toast.LENGTH_SHORT).show();
}
After, I setup the receiver with the openFile() method:
BroadcastReceiver onComplete=new BroadcastReceiver() {
public void onReceive(Context ctxt, Intent intent) {
Toast.makeText(getApplicationContext(), "ההורדה הסתיימה",
Toast.LENGTH_LONG).show();
openFile("GMU.pdf");
}
};
public void openFile(String fileName){
try {
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), fileName);
Uri path = Uri.fromFile(file);
Log.i("Fragment2", String.valueOf(path));
Intent pdfOpenintent = new Intent(Intent.ACTION_VIEW);
pdfOpenintent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
pdfOpenintent.setDataAndType(path, "application/pdf");
this.startActivity(pdfOpenintent);
} catch (ActivityNotFoundException e) {
Toast.makeText(ActiveAuctionsActivity.this, "error", Toast.LENGTH_LONG).show();
}
}
Again, the file does download, but doesn't open.
What am I doing wrong, could you please advise me?
EDIT
I also tried the code below as my openFile() but that also doesn't work:
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), fileName);
Uri path = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".provider", file);
Intent pdfOpenintent = new Intent(Intent.ACTION_VIEW);
pdfOpenintent.setDataAndType(path, pdfOpenintent.getType());
pdfOpenintent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
pdfOpenintent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
try {
ActiveAuctionsActivity.this.startActivity(pdfOpenintent);
} catch (ActivityNotFoundException e) {
pdfOpenintent.setType("application/*");
startActivity(Intent.createChooser(pdfOpenintent, "No Application found to open File - " + fileName));
}
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
I have used CN1CircleProgress library while downloading pdf files. It works great if the pdf file is small. But for larger pdf files eg 30 Mb, the circle fills to 100% 2-3 times very quickly and then again it starts to download to 20-30% & download stops. The file downloaded is currupted & cannot be opened in pdf viewer. I have checked it in iOS & android devices. In simulator it just downloads to certain percent, then it stops
downloadPdfButton.addActionListener((e) -> {
pdfUrlSelected = "http://roundtablenepal.org.np/uploadEpubs/57cbcc4e76258.pdf";
pdfFileNameIdSelected = currentPdfSelected.get("magazine_title");
filename = dir + sep;
filename = filename + pdfFileNameIdSelected + ".pdf";
FileSystemStorage.getInstance().mkdir(dir);
Slider downloadSlider = new Slider();
if (!FileSystemStorage.getInstance().exists(filename)) {
downloadPdfFromUrl(f, pdfUrlSelected, filename, true, downloadSlider, findCancelDownload(f));
}
});
private boolean downloadPdfFromUrl(Form f, String url, final String fileName, boolean storage, final Slider slider, Button cancel) {
crPdf = new ConnectionRequest();
crPdf.resume();
crPdf.setPost(false);
crPdf.setDuplicateSupported(true);
crPdf.setFailSilently(true);
crPdf.setUrl(url);
crPdf.setTimeout(15000);
crPdf.setDestinationFile(fileName);
final CircleFilledProgress p = new CircleFilledProgress();
p.setProgress(0);
f.add(BorderLayout.CENTER, p);
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());
}
}
}
});
slider.addDataChangedListener(new DataChangedListener() {
#Override
public void dataChanged(int type, int index) {
p.setProgress(index);
}
});
NetworkManager.getInstance().addToQueueAndWait(crPdf);
cancel.addActionListener((e) -> {
crPdf.kill();
});
return crPdf.getResponseCode() == 200;
}
I suggest opening the network monitor, I'm guessing you are getting a redirect which updates the progress then the redirect leads to an error page for some reason.
I have saved an image using fileSystemStorage with the name of "profile.png". But how cab I read the image and display it afterward. I had used Storage.getInstance.writeObject and
readObject before but I think it doesnt work for images.
userImg.addActionListener((e) -> {
Display.getInstance().openGallery(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
try {
if (evt == null) {
System.out.println("user cancelled");
return;
}
eventImgpath = (String) evt.getSource();
Image i = Image.createImage(eventImgpath);
Image profileImg = i.scaledWidth(Display.getInstance().getDisplayWidth() / 3);
InputStream stream = FileSystemStorage.getInstance().openInputStream(eventImgpath);
OutputStream out = Storage.getInstance().createOutputStream("profile.png");
Util.copy(stream, out);
Util.cleanup(stream);
Util.cleanup(out);
userImg.setIcon(profileImg);
userImg.setPreferredH(20 + Display.getInstance().getDisplayWidth() / 3);
userImg.getParent().revalidate();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}, Display.GALLERY_IMAGE);
});
I have one more question. How can I re-adjust the image as an icon in a label? for eg we can readjust or drag to repostion cover img in facebook before saving it. Since it is a profile image while saving it sometime the face is not shown so I need to reposition the image and save it as a label icon. Is there any example for it?
Thankyou