How to call phone plugin in javascript - javascript

Ok I am trying to implement an phone gap plugin, that consists of two parts. I am using cordova 2.0.0 and eclipse.
Here is the java part:
package org.apache.cordova;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.cordova.api.Plugin;
import org.apache.cordova.api.PluginResult;
import org.json.JSONArray;
import android.graphics.Bitmap;
import android.os.Environment;
import android.view.View;
public class Screenshot extends Plugin {
#Override
public PluginResult execute(String action, JSONArray args, String callbackId) {
// starting on ICS, some WebView methods
// can only be called on UI threads
final Plugin that = this;
final String id = callbackId;
super.cordova.getActivity().runOnUiThread(new Runnable() {
//#Override
public void run() {
View view = webView.getRootView();
view.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache());
view.setDrawingCacheEnabled(false);
try {
File folder = new File(Environment.getExternalStorageDirectory(), "Pictures");
if (!folder.exists()) {
folder.mkdirs();
}
File f = new File(folder, "screenshot_" + System.currentTimeMillis() + ".png");
FileOutputStream fos = new FileOutputStream(f);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
that.success(new PluginResult(PluginResult.Status.OK), id);
} catch (IOException e) {
that.success(new PluginResult(PluginResult.Status.IO_EXCEPTION, e.getMessage()), id);
}
}
});
PluginResult result = new PluginResult(PluginResult.Status.NO_RESULT);
result.setKeepCallback(true);
return result;
}
}
Here is the javascript part:
cordova.define("cordova/plugin/screenshot", function(require, exports, module) {
var exec = require('cordova/exec');
/**
* This class exposes the ability to take a Screenshot to JavaScript
*/
var Screenshot = function() {};
/**
* Save the screenshot to the user's Photo Library
*/
Screenshot.prototype.saveScreenshot = function() {
exec(null, null, "Screenshot", "saveScreenshot", []);
};
var screenshot = new Screenshot();
module.exports = screenshot;
});
if (!window.plugins) {
window.plugins = {};
}
if (!window.plugins.screenshot) {
window.plugins.screenshot = cordova.require("cordova/plugin/screenshot");
}
I am trying to call this with another javascript function on another page, but without success. I hide the anchors of an image on a canvas, then this line:
setTimeout(takeScreenShot,500);
EDIT -- made after Simon MacDonald's answer
this then relates to a javascript function:
function takeScreenShot() {
window.plugins.screenshot.saveScreenshot();
}
The following java prints:
System.out.println(folder);
System.out.println("screenshot_" + System.currentTimeMillis() + ".png");
Produce the following results:
/mdt/sdcard/Pictures
screenshot_1347893081276.png
EDIT After turning the device off and on again, the screenshots I took appeared, the phone seems to cache them, and not actually store them to the selected folder.
I have ensured that my config.xml and my android manifest have the right permissions and lines of code. Anyone see where im going wrong?

nowhere in your code do you ever call the saveScreenshot method. Your takeScreenShot method should look like this:
function takeScreenShot() {
window.plugins.screenshot.saveScreenshot();
}
Then the screen shot should be saved in "/sdcard/Pictures". This will work if:
You remembered to put a plugin line into your config.xml for the screen shot plugin
You mentioned this is on another page so make sure that page has a script tag for screenshot.js.

Did you try with the Obsolute Path?
File sdCard = Environment.getExternalStorageDirectory();
File folder = new File (sdcard.getAbsolutePath() + "Pictures");

Related

JavaFX WebView: can't get JS bridge to work in Java11+

I can't get the Java / Javascript bridge to work on Java11 and Java13. The bridge seems to work fine i Java8 and Java10.
Here is essentially the same code as https://stackoverflow.com/a/34840552/11329518, which again works for me on Java8 and Java10:
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import javafx.application.Application;
import javafx.concurrent.Worker.State;
import javafx.scene.control.ButtonType;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebEvent;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import netscape.javascript.JSObject;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
JavaBridge bridge;
WebEngine webEngine;
#Override
public void start(Stage primaryStage) throws MalformedURLException {
final URL url = new File("C:/test.html").toURI().toURL();
WebView webView = new javafx.scene.web.WebView();
webEngine = webView.getEngine();
webEngine.load(url.toExternalForm());
webEngine.setJavaScriptEnabled(true);
webEngine.setOnAlert(Main::showAlert);
webEngine.getLoadWorker().stateProperty().addListener((ov, oldState, newState) -> {
if (newState == State.SUCCEEDED) {
System.out.println("READY");
JSObject jsobj = (JSObject) webEngine.executeScript("window");
bridge = new JavaBridge();
jsobj.setMember("bridge", bridge);
}
});
primaryStage.setScene(new javafx.scene.Scene(webView, 300, 300));
primaryStage.show();
}
// Shows the alert, used in JS catch statement
private static void showAlert(WebEvent<String> event) {
javafx.scene.control.Dialog<ButtonType> alert = new javafx.scene.control.Dialog<>();
alert.getDialogPane().setContentText(event.getData());
alert.getDialogPane().getButtonTypes().add(ButtonType.OK);
alert.showAndWait();
}
public class JavaBridge {
public void hello() {
System.out.println("hello");
}
}
}
with test.html containing the Javascript:
<button onclick="try{bridge.hello();}catch(err){alert(err.message);}">call java</button>
What's going on?
I get the following error when clicking the button:
bridge.hello is not a function. (In 'bridge.hello()', 'bridge.hello' is undefined)
I can't reproduce your issue with JavaFX 13 or 14-ea+6, using Java 11 (OpenJDK 11.0.2) or Java 13 (OpenJDK 13).
However I can reproduce the issue, if I remove the strong reference to JavaBridge and I use Java 11.
This:
jsobj.setMember("bridge", new JavaBridge());
fails with the same error you have posted, with Java 11. But when using Java 13 (OpenJDK 13), that works fine (and also with Java 12).
Are you using other Java vendors? Can you try with OpenJDK https://jdk.java.net/13/?
There are two things that resolved this issue with OpenJDK 14 and JavaFx 14
Hard Reference to Bridge Object
bridge = new JavaBridge(); // create Bridge before hand
webEngine.getLoadWorker().stateProperty().addListener((ov, oldState,
newState) -> {
if (newState == State.SUCCEEDED) {
System.out.println("READY");
JSObject jsobj = (JSObject) webEngine.executeScript("window");
jsobj.setMember("bridge", bridge);
}
});
Use Bridge in Javascript/HTML page after the page is loaded
window.onload = function() {
bridge.hello();
}

Can we give bulk url's in this code?

URL url = new URI("http://tamilblog.ishafoundation.org/").toURL();
I want to give 100 url in this connector?
I have the code to run single home page to extract its data
I need to get more contents From several links !
Is it any way possible ?
Here is my code
import java.io.IOException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
public class NewClass {
public static void main(String[] args) throws IOException {
Document doc = Jsoup.connect("http://tamilblog.ishafoundation.org").get();
Elements section = doc.select("section#content");
Elements article = section.select("article");
for (Element a : article) {
System.out.println("Title : \n" + a.select("a").text());
System.out.println("Article summary: \n" + a.select("div.entry-summary").text());
}
}
}
I got output from this single page Now i need to get it from several pages (100+links) at once.
And to save it in a document.

Jasper Report : "Document has no pages"

I have a problem when I run this code. I get always this message : "Document has no pages" with a blank page in the pdf file .
Note: I'm using NetBeans IDE 7.2 Beta.
Jar files imported are:
com.lowagie.text-2.1.7.jar
commons-beanutils-1.5.jar
commons-collections-2.1.jar
commons-digester-2.1.jar
commons-javaflow.jar
commons-logging-1.3.jar
jasperreports-5.5.1.jar
javax.servlet.jar
I need your help,please.
this is my code :
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Currency;
import java.util.HashMap;
import javax.swing.JFrame;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.swing.JRViewer;
public class Report extends JFrame{
public Report(String month,int year){
try{
//load the driver
Class.forName("com.mysql.jdbc.Driver");
String url="jdbc:mysql://localhost:3306/motor";
String user="root";
String pass="";
Connection cn=DriverManager.getConnection(url,user,pass);
System.out.println("connected in report");
PreparedStatement ps = cn.prepareStatement("select number,title,name,ikar,echtirak,price,tarakom from users order by number asc");
ResultSet rs;
rs=ps.executeQuery();
JasperPrint jasperPrint=null;
HashMap<String, Object> mapParameters = new HashMap <String, Object>();
// jrxml compiling process
JasperReport jasperReport = JasperCompileManager.compileReport("C:/Users/user/Documents/NetBeansProjects/MotorApp/MyReports/motorReport.jrxml");
int i=1;
while(rs.next()){
mapParameters.put("Name", rs.getString("title")+" "+rs.getString("name"));
mapParameters.put("Number",rs.getString("number"));
mapParameters.put("Ikar",rs.getString("ikar"));
mapParameters.put("Amperage",rs.getString("echtirak")+" A");
mapParameters.put("tarakom",rs.getString("tarakom")+" $");
mapParameters.put("monthPrice",rs.getString("price")+" $");
Integer total=Integer.parseInt(rs.getString("price"))+Integer.parseInt(rs.getString("tarakom"));
mapParameters.put("totalPrice",total+" $");
mapParameters.put("monthYear",year+" "+month);
try{
System.out.println("Filling report...");
jasperPrint = JasperFillManager.fillReport(jasperReport, mapParameters,cn);
JRViewer viewer = new JRViewer(jasperPrint);
System.out.println("Done!");
JasperExportManager.exportReportToPdfFile(jasperPrint,"C:/Users/user/Desktop/"+month+" "+year+".pdf");
}catch(JRException elle){
System.out.println(elle.getMessage());
}
}
}catch(Exception ev){
System.out.println(ev.getMessage());
}
}
}
I truly appreciate your help.
My first thought is on the motorReport.jrxml file. It may have some issues on its content. Try reducing the contents of the report to a point where the code works and the reports can display properly. It may give you a clue to the cause of the problem. Then get back here with more specifics if you still can't solve this problem.
mapParameters in your code is not records of DataSource. It is parameters of report, therefore report haven't records.
One of the possible solutions: convert ResultSet into BeanCollection, make JRBeanCollectionDataSource and pass it into fillReport.
Make bean for saving result of query.
public class UserBean {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
....
}
For example result is
List myList = new ArrayList<UserBean>();
Convert into collection example here stackoverflow.com/questions/17206523/put-resultset-values-into-collection-object-then-add-to-arraylist
After convert you must call fillReport like this:
jasperPrint = JasperFillManager.fillReport(jasperReport, new HashMap<String,Object>, new JRBeanCollectionDataSource(myList));

Phonegap - How to access file in www-folder?

I saw multiple solutions how to access a file in the www folder but no solution works for me. I test the application under iOS with the iOS-simulator.
I want to access the file test.txtin the www folder.
My current solution looks like this:
var filePathURI = getPhoneGapPath() + "test.txt";
window.resolveLocalFileSystemURI(filePathURI, onResolveSuccess, onFail);
function getPhoneGapPath() {
'use strict';
var path = window.location.pathname;
var phoneGapPath = path.substring(0, path.lastIndexOf('/') + 1);
return phoneGapPath;
};
This solution does not work for me. I get an error with errorCode = 2 which obviously means FileError.SECURITY_ERR. However I try, with resolveLocalFileSystemURI I can not access to the file.
INFO: I tried following filePathURI:
/Users/UserName/Library/Application%20Support/iPhone%20Simulator/7.0/Applications/GUID/AppName.app/www/test.txt
file:///Users/UserName/Library/Application%20Support/iPhone%20Simulator/7.0/Applications/GUID/AppName.app/www/test.txt
Can anyone give me a working solution?
I would suggest utilizing the resolveLocalFileSystemURL method provided by PhoneGap's file plugin. You can then use the cordova.file.applicationDirectory property to access where your www folder is located.
Make sure you install the plugin: $ cordova plugin add org.apache.cordova.file
Then you could use an object such as the following to parse the files and do whatever is needed:
var FileManager = {
/**
* Execute this.entryHandler against all files and directories in phonegap's www folder
*/
run: function () {
window.resolveLocalFileSystemURL(
cordova.file.applicationDirectory + 'www/',
this.directoryFoundHandler,
this.errorHandler
);
},
/**
* The directory has been successfully read. Now read the entries.
*
* #param {DirectoryEntry} directoryEntry
*/
directoryFoundHandler: function (directoryEntry) {
var directoryReader = directoryEntry.createReader();
directoryReader.readEntries(
this.entryHandler,
this.errorHandler
);
},
/**
* Files were successfully found. Parse them!
*
* #param {Array.<FileEntry>} entries
*/
entryHandler: function (entries) {
entries.forEach(function (entry) {
// Deal with your files here
if (entry.isDirectory) {
// It's a directory might need to loop through again
} else {
// It's a file, do something
}
});
},
/**
* #param {FileError} error
*/
errorHandler: function (error) {
console.log("ERROR", error);
}
};
I load my language files with ajax like this...
$.get( "test.txt", function( data ) {
console.log( "Load was performed.", data );
});
I think for your solution you have to add read access to your app --> config.xml
<feature name="http://api.phonegap.com/1.0/file" />
Try this, part of my functions. You first need to get the file system and then get the root path. Modify it to fit your needs.
The you just can do the following.
app_FileSystem for me is a global variable that gets assigned by GetAppFS
After getting the FS and the root path you can just simple use a ajax call or a getjson call with the appropriate dataType set. It works for me.
Also check the doc which is helpful:
http://docs.phonegap.com/en/3.3.0/cordova_file_file.md.html#LocalFileSystem
app_FileSystem.root.fullPath; // Get the app file system root full path
function GetAppFS ()
{
var self = this;
self.state = ""; // store the state of the process for debuggin purposes
self.fileSystem = {};
window.requestFileSystem ( LocalFileSystem.PERSISTENT, 0, getFileSystemSuccess, dispatchFailure );
/**
*
* Called when we receive a valid file system. Once we do that, we need to ask for all
* the documents within the file system.
*
*/
function getFileSystemSuccess ( fileSystem )
{
self.state = "Received File System";
self.fileSystem = fileSystem;
app_FileSystem = fileSystem;
OnFSReady ();
};
/**
*
* All our functions need a failure callback, so we provide dispatchFailure. If an error occurs, we'll
* at least log it to the console, and then call the failure function attached to self.failure(), if any.
*
*/
function dispatchFailure ( e )
{
// some sort of failure :-(
console.log ("While " + self.state + ", encountered error: " + JSON.stringify(e));
alert ("dev FS ERROR ");
};
};
As I just ran into the same problem but did not want to use jQuery, I thought I post my solution here as well.
But before that an import remark: The files in the www folder of Cordova / Phone Gap are stored in the Android world as so called assets which means:
They are part of the .apk distribution file which is a zipped archive. Android reads the files directly from this .apk file and does not store these files separately in the local file system.
Therefore the files are read only and cannot be accessed with the Cordova File plugin.
If you take a deep dive in the corresponding Android sources of Cordova you can see, that Cordova filters all URIs with a 'file' scheme, whose path starts with '/android_asset/' and handles them specially using Android's asset access functions. (Would be interesting to hear from the iOS experts how Cordova handles it in their world.)
This means all in all that using a XMLHttpRequest is probably the only portable way to access www folder files if you need access to the file contents. (If you only need the path to the file for some system functions other methods may work as well.)
Here is the code, filename is the path within the www folder without a "www/" prefix:
var readFileInWWWFolder = function(filename, onSuccess, onFailure){
var request = new XMLHttpRequest();
request.onload = function() {
var arrayBuffer = request.response;
if (arrayBuffer) {
onSuccess(new Uint8Array(arrayBuffer));
}
else {
onFailure();
}
};
request.open("GET", filename, true);
request.responseType = "arraybuffer";
request.send();
};
This has been tested with Cordova 4.3.0 and Android 4.4.2 (Kitkat).
One trick that works is to fs.download each file from the www folder into Cordova’s persistent file system. See my original post.
First, in Terminal:
npm install cordova-promise-fs
cordova plugin add cordova-plugin-file --save
cordova plugin add cordova-plugin-file-transfer --save
Then, in your front-end:
import CordovaPromiseFS from 'cordova-promise-fs'
const fs = CordovaPromiseFS({
persistent: true,
storageSize: 200 * 1024 * 1024,
concurrency: 3
})
If you use React, the above has to be declared before the component Class is created, while the below code should be in its own function inside the component Class. See my GitHub comment for more details.
window.resolveLocalFileSystemURL(
cordova.file.applicationDirectory + 'www/epubs/alice.epub',
// If successful...
(fileSystem) => {
const downloadUrl = fileSystem.toURL()
const localUrl = 'alice.epub' // the filename it is stored as in the device
fs.download(
downloadUrl,
localUrl,
(progressEvent) => {
if (progressEvent.loaded && progressEvent.total) {
console.log('progress', Math.round((progressEvent.loaded / progressEvent.total) * 100))
}
}
).then((filedata) => {
return fs.toInternalURL(localUrl)
})
.then((localPath) => {
this.setState({ epubPath: localPath })
}).catch((error) => {
console.log('some error happend', error)
})
},
// If unsuccessful
(err) => {
console.log(err)
}
)

How to pass a camera image to mail as an attachment. (Android, iOS, Windows Phone, Phonegap)

I am developing an app for my work (social housing) and I want it to be able to allow the user to take a photo and attach it to an email so they can send it to us (pictures of repairs etc)
I'm using Phonegap and Eclipse as I want the app to be cross platform but am testing in Android primarily at the moment. Is there a way to do this? I am currently using the code below with no avail.
<script typr="text/javascript" charset="utf-8">
function camera()
{
navigator.camera.getPicture(onSuccess, onFail, { quality: 20,
destinationType: Camera.DestinationType.DATA_URL
});
function onSuccess(imageData) {
var image = document.getElementById('image');
var data = "data:image/jpeg;base64," + imageData;
var link = "mailto:johnsmith#gmail.com?body="+data+"&subject=john smith";
window.location.href = link;
}
function onFail(message) {
alert('Failed because: ' + message);
}
}
</script>
So far I've tried passing the data through to the mail app using the mailto: &attachment method but that never attaches an image (most mail apps treat this as a security hole). Then I tried to embed the base64 code of the image in the body of the email (as shown above). Unfortunately the base64 just displays as plain text and makes mail unresponsive. I've also tried using the image URI instead of the Base64 method in Phonegap but that throws an 'image.URI is not defined' error in my logcat.
Is this possible? I know I can use intents for just android as detailed in another question here but this won't work on iOS etc.
Any help would be greatly appreciated.
EDIT 02/12/2012
What I'm trying to achieve here is the same functionality you get in the native Android gallery/camera app. After you take a picture you have share options, one of which is mail. If you chose to share via mail the image is passed to the mail app as an attachment. Is there any way I can implement this same functionality in my app?
So it looks like there is no 'one size fits all' solution for this problem.
The mailto: method just doesn't pass attachments in most modern mail apps as it's seen as a security risk. So regardless of whether its an imageURI or a base64 encoded image, mailto: just won't work. The passing of 'subject' and 'body' works well though for anyone that wants to use the above code for pre-filling in an email with no attachments.
After posing this question elsewhere it looks like I'll need to use a phonegap plugin (emailComposer for iOS and WebIntent for Android) in order to pass an image sucessfully to a mail app from my phonegap app.
Thanks.
use this JAVA code to send Email with photo and text.
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.Security;
import java.util.Properties;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
public class GMailSender extends javax.mail.Authenticator {
private String mailhost = "smtp.gmail.com";
private String user;
private String password;
private Session session;
static {
Security.addProvider(new JSSEProvider());
}
public GMailSender(String user, String password) {
this.user = user;
this.password = password;
Properties props = new Properties();
props.setProperty("mail.transport.protocol", "smtp");
props.setProperty("mail.host", mailhost);
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.port", "465");
props.put("mail.smtp.socketFactory.port", "465");
props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.socketFactory.fallback", "false");
props.setProperty("mail.smtp.quitwait", "false");
session = Session.getDefaultInstance(props, this);
}
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(user, password);
}
public synchronized void sendMail(String subject, String body, String sender, String recipients) throws Exception {
try {
MimeMessage message = new MimeMessage(session);
DataHandler handler = new DataHandler(new ByteArrayDataSource(body.getBytes(), "text/plain"));
message.setSender(new InternetAddress(sender));
message.setSubject(subject);
message.setDataHandler(handler);
if (recipients.indexOf(',') > 0)
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(recipients));
else
message.setRecipient(Message.RecipientType.TO, new InternetAddress(recipients));
Transport.send(message);
} catch (Exception e) {
}
}
public synchronized void sendMail(String subject, String body, String senderEmail, String recipients, String filePath,String logFilePath) throws Exception {
boolean fileExists = new File(filePath).exists();
if (fileExists) {
String from = senderEmail;
String to = recipients;
String fileAttachment = filePath;
// Define message
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
message.setSubject(subject);
// create the message part
MimeBodyPart messageBodyPart = new MimeBodyPart();
// fill message
messageBodyPart.setText(body);
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(messageBodyPart);
// Part two is attachment
messageBodyPart = new MimeBodyPart();
DataSource source = new FileDataSource(fileAttachment);
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName("screenShoot.jpg");
multipart.addBodyPart(messageBodyPart);
//part three for logs
messageBodyPart = new MimeBodyPart();
DataSource sourceb = new FileDataSource(logFilePath);
messageBodyPart.setDataHandler(new DataHandler(sourceb));
messageBodyPart.setFileName("logs.txt");
multipart.addBodyPart(messageBodyPart);
// Put parts in message
message.setContent(multipart);
// Send the message
Transport.send(message);
}else{
sendMail( subject, body, senderEmail, recipients);
}
}
public class ByteArrayDataSource implements DataSource {
private byte[] data;
private String type;
public ByteArrayDataSource(byte[] data, String type) {
super();
this.data = data;
this.type = type;
}
public ByteArrayDataSource(byte[] data) {
super();
this.data = data;
}
public void setType(String type) {
this.type = type;
}
public String getContentType() {
if (type == null)
return "application/octet-stream";
else
return type;
}
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(data);
}
public String getName() {
return "ByteArrayDataSource";
}
public OutputStream getOutputStream() throws IOException {
throw new IOException("Not Supported");
}
}
}

Categories

Resources