Cannot read property 'messageHandlers' of undefined - javascript

I want to pass JavaScript variable to Swift.
I get an error in JavaScript & search for that but I didn't get any result.
The error is:
TypeError: Cannot read property 'messageHandlers' of undefined
Any one can help?
My code in Xcode:
import UIKit
import WebKit
class ViewController: UIViewController,WKScriptMessageHandler,WKNavigationDelegate {
var webView = WKWebView()
override func viewDidLoad() {
super.viewDidLoad()
webView.frame = view.bounds
webView.navigationDelegate = self
let url = URL(string: "MyUrl")!
let urlRequest = URLRequest(url: url)
webView.load(urlRequest)
webView.autoresizingMask = [.flexibleWidth,.flexibleHeight]
view.addSubview(webView)
let userContentController = WKUserContentController()
userContentController.add(self, name: "test")
}
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
print("Name: \(message.name)")
print("Body: \(message.body as! String)")
}
}
And in JavaScript:
click: event => {
window.webkit.messageHandlers.test.postMessage("hi");
}

After adding the "test" message handler, you need to add it to your webView's configuration, but you are not doing so.
By including this message handler into your WKUserContentController object, your webView will define a new function window.webkit.messageHandlers.name.postMessage(messageBody) that can be called in all frames.
Try changing your viewDidLoad() to the following:
override func viewDidLoad() {
super.viewDidLoad()
let config = WKWebViewConfiguration()
let userContentController = WKUserContentController()
userContentController.add(self, name: "test")
config.userContentController = userContentController
webView = WKWebView(frame: view.bounds, configuration: config) // Create webView with the configuration
webView.navigationDelegate = self
let url = URL(string: "MyUrl")!
let urlRequest = URLRequest(url: url)
webView.load(urlRequest)
webView.autoresizingMask = [.flexibleWidth,.flexibleHeight]
view.addSubview(webView)
}

Related

Failed to call javascript method from Swift code using WKWebView

I have a method in reacts form which I have loaded on WKWebView
window.initWithInfo = (credsObj) => {
}
I am using the following code to setup the WKWebView:
let config = WKWebViewConfiguration()
let preferences = WKPreferences()
preferences.javaScriptEnabled = true
preferences.javaScriptCanOpenWindowsAutomatically = true
let userContentController = WKUserContentController()
userContentController.add(self,name:"messageHandler")
config.preferences = preferences
config.userContentController = userContentController
webView = WKWebView(frame:.zero, configuration: config)
view.addSubview(webView)
let urlString = "https://example.com"
if let url = URL(string: urlString) {
webView.load(URLRequest(url: url))
}
I am getting the callback message from javascript to iOS native userContentController but javascript method window.initPayrixInfo = (payrixCredsObj) is not getting called using evaluatejavascript from the userContentController
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
if (message.name == "messageHandler") {
self.webView.evaluateJavaScript("initWithInfo(\(["api_key": "1233654", "api_token": "654321"])") { result, error in
if(error != nil) {
print(error)
}
}
}
}
How to make this work?
communicate between javascript and native iOS platform.

Axios get Request not receiving data

I am trying to download the content of my s3 bucket, and when I hit the API endpoint the data shows in my Intellij console, but in my postman and browser console I simply get an empty object.
Is there a certain why I am supposed to receive this in an Axios request?
Axios -
downloadLocations() {
axios.get("http://localhost:8080/api/v1/targetLocation/downloadSearchData")
.then((res) => {
console.log(res.data)
// We will need to retrieve the data into a downloadable blob
// const content = new Blob([JSON.stringify(???)],{ type: 'text/plain;charset=utf-8' })
// const fileName = `test.txt`
// saveAs(content, fileName)
}, (error) => {
console.log(error);
});
}
Service -
public ByteArrayOutputStream downloadSearchData() throws IOException {
BasicAWSCredentials awsCredentials = new BasicAWSCredentials(awsAccessKey, awsSecretKey);
AmazonS3 s3client = AmazonS3ClientBuilder
.standard()
.withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
.withRegion(awsRegion)
.build();
var s3Object = s3client.getObject("downloadable-cases", "7863784198_2021-08-16T13_30_06.690Z.json");
var out = new ByteArrayOutputStream();
try (var in = s3Object.getObjectContent()) {
in.transferTo(out);
}
System.out.println(out);
return out;
}
Controller -
#GetMapping(value = "downloadSearchData")
public ByteArrayOutputStream downloadSearchData() throws IOException {
return targetLocationService.downloadSearchData();
}
Ok, I found the answer. I changed the Service and Controller return value to String and it now works perfectly
public String downloadSearchData() throws IOException {
BasicAWSCredentials awsCredentials = new BasicAWSCredentials(awsAccessKey, awsSecretKey);
AmazonS3 s3client = AmazonS3ClientBuilder
.standard()
.withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
.withRegion(Regions.GovCloud)
.build();
var s3Object = s3client.getObject("downloadable-cases", "7863784198_2021-08-16T13_30_06.690Z.json");
var out = new ByteArrayOutputStream();
try (var in = s3Object.getObjectContent()) {
in.transferTo(out);
}
return out.toString();
}

How to send queryStringParameters with invokeApi command

The full path to the endpoint with the query string parameters is:
https://api.mydomain.com/getData?param_01=value_01&param_02=value_01
After importing the 'aws-api-gateway-client'
var apigClientFactory = require('aws-api-gateway-client').default;
I go ahead and configure the variables:
let url = 'https://api.mydomain.com'
let pathTemplate = '/getData?param_01=value_01&param_02=value_01';
let method = 'GET';
let params = '';
let additionalParams = '';
let body = '';
var client = apigClientFactory.newClient({
invokeUrl: url,
accessKey: 'my-accessKeyId',
secretKey: 'my-secretAccessKey',
sessionToken: 'my-sessionToken',
region: 'MY_AWS_REGION'
});
Next invoke endpoint with:
client
.invokeApi(params, pathTemplate, method, additionalParams, body)
.then(function(res) {
console.log("...res:", res);
})
.catch(function(err) {
console.log("...err:", err);
});
But it fails with the error
The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details
Is there a way to send the queryStringParameters with invokeApi command?
let params = {};
let pathTemplate = '/getData';
let additionalParams = {
queryParams: {
param0: 'value0',
param1: 'value1'
}
};
aws-api-gateway-client - npm

How to send in media[] parameters for update with media API call of twitter using javascript

I'm implementing twitter status update in my phonegap/cordova application on android. all the work is going perfect even simple text can be update on my twitter status.. but when try to upload media api, it response error code 195 and message is Missing or invalid url paramter
I'm following this example
var mediaUrl = 'http://fbrell.com/f8.jpg';
//update_with_media.json
//update.json
oauth.post('https://api.twitter.com/1.1/statuses/update_with_media.json',
{ 'status' : 'testing message', // javascript OAuth encodes this
'media[]' : mediaUrl
},
function(data) {
console.log('success posted');
console.log(JSON.stringify(data));
var entry = JSON.parse(data.text);
// just for eg.
tweetPostDone();
},
function(errorData) {
console.log('error on posted');
console.log(JSON.stringify(errorData));
}
);
}
What I'm doing wrong with javascript code on media[] parameter?
Twitter response:
"text": {
"errors": [
{
"code": 195,
"message": "Missing or invalid url parameter."
}
]
},
I solved my problem by create a custom phonegap plugin.
Step#1 - Create javascript file on /assets/www/js/UploadTwitterMedia.js
(function() {
/* This increases plugin compatibility */
var cordovaRef = window.PhoneGap || window.Cordova || window.cordova; // old to new fallbacks
/**
* The Java to JavaScript Gateway 'magic' class
*/
function UploadTwitterMedia() { }
UploadTwitterMedia.prototype.uploadImage = function(params, win, fail) {
cordovaRef.exec(win, fail, "UploadTwitterMedia", "uploadImage", [params]);
};
cordovaRef.addConstructor(function() {
if (!window.plugins) {
window.plugins = {};
}
if (!window.plugins.UploadTwitterMedia) {
window.plugins.UploadTwitterMedia = new UploadTwitterMedia();
}
});
})();
Step#2 - Create a Java Class File in org.apache.cordova.plugins and name it UploadTwitterMedia.java
package org.apache.cordova.plugins;
/**
* A phonegap plugin that upload media on twitter profile by using url address
*
* #author mcaesar
* #lincese MIT.
*/
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import org.apache.cordova.api.Plugin;
import org.apache.cordova.api.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import twitter4j.auth.OAuthAuthorization;
import twitter4j.conf.Configuration;
import twitter4j.conf.ConfigurationBuilder;
import twitter4j.media.ImageUpload;
import twitter4j.media.ImageUploadFactory;
import android.provider.SyncStateContract.Constants;
import android.util.Log;
public class UploadTwitterMedia extends Plugin {
#Override
public PluginResult execute(String action, JSONArray args, String callbackId) {
Log.d("upload action on UploadTwitterMedia.java", action);
if (!action.equals("uploadImage")) {
return new PluginResult(PluginResult.Status.INVALID_ACTION);
}
try {
String uploadImageurl = "";
String accessToken = "";
String accessSecret = "";
String statusText = "";
JSONObject params = args.getJSONObject(0);
uploadImageurl = params.getString("urllink");
accessToken = params.getString("accessToken");
accessSecret = params.getString("accessSecret");
statusText = params.getString("statusText");
Log.d("UploadImageUrl", uploadImageurl);
Log.d("accessToken", accessToken);
Log.d("accessSecret", accessSecret);
Log.d("statusText", statusText);
return this.uploadImage(uploadImageurl, accessToken, accessSecret, statusText, callbackId);
} catch (JSONException e) {
e.printStackTrace();
return new PluginResult(PluginResult.Status.JSON_EXCEPTION, e.getMessage());
} catch (InterruptedException e) {
e.printStackTrace();
return new PluginResult(PluginResult.Status.ERROR, e.getMessage());
}
}
private PluginResult uploadImage(String imageUrl, String accessToken, String accessSecret, String statusText, String callbackId) throws InterruptedException, JSONException {
// TODO Auto-generated method stub
String url;
String consumerKey = "xxxxxxxxxxxxxxxxxxxx";
String consumerSecret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
String oth = accessToken;
String src = accessSecret;
Configuration conf = new ConfigurationBuilder()
.setOAuthConsumerKey(consumerKey)
.setOAuthConsumerSecret(consumerSecret)
.setOAuthAccessToken(oth).setOAuthAccessTokenSecret(src)
.build();
OAuthAuthorization auth = new OAuthAuthorization(conf);
//ImageUpload upload = ImageUpload.getTwitpicUploader(Constants.twitpic_api_key, auth);
ImageUpload upload = new ImageUploadFactory(conf).getInstance(auth);
Log.d("Twitter Native Function in UploadTwitterMedia.java", "Start sending image...");
try {
url = upload.upload(" ", new URL(imageUrl).openStream(),statusText);
} catch (Exception e) {
//e.printStackTrace();
return new PluginResult(PluginResult.Status.ERROR, ""+e.getMessage());
}
return new PluginResult(PluginResult.Status.OK, "Saved successfully!");
}
}
Step#3 - Download latest version of Twitter library for android from twitter4j.org
Step#4 - Add a line in the plugin.xml or config.xml in res/xml/
<plugin name="UploadTwitterMedia" value="org.apache.cordova.plugins.UploadTwitterMedia"/>
Step#5 - Now call to upload method.
post: function(){
/*
oauth.post('https://api.twitter.com/1.1/statuses/update.json',
{ 'status' : theTweet+' Test ', // javascript OAuth encodes this
'media[]': base64String
}
function(data) {
console.log('success posted');
console.log(JSON.stringify(data));
var entry = JSON.parse(data.text);
console.log(entry);
// just for eg.
tweetPostDone();
},
function(errorData) {
console.log('error on posted');
console.log(errorData);
console.log(JSON.stringify(errorData));
}
);
*/
/*
oauth.push("https://api.twitter.com/1.1/statuses/update_with_media.json",
imageURI.substr(imageURI.lastIndexOf("/") + 1),
new FileUploadOptions("media", "image.jpg", "image/jpeg", {status:tweetStatus}, {}),
onTweetSuccess,
onTweetError
);
*/
var storedAccessData, rawData = localStorage.getItem(twitterKey);
storedAccessData = JSON.parse(rawData); // Paring Json
window.plugins.UploadTwitterMedia.uploadImage(
{
urllink : 'http://fbrell.com/f8.jpg',
accessToken : storedAccessData.accessTokenKey,
accessSecret : storedAccessData.accessTokenSecret,
statusText : 'Hello World...'
},
function(result) {
console.log('success');
console.log(result);
}, function(error) {
console.log('error');
console.log(error)
});
}
hope and when i call the Twitter.post() method it will post on provided valid acessToken and accessSecret. If success, it will call the success function
function(result) {
console.log('success');
console.log(result);
},
else call error function
function(error) {
console.log('error');
console.log(error)
}
Note: Update the consumerKey & consumerSecret with your twitter application in UploadTwitterMedia.java file.

why i am getting responseText(From Servlet to javaScript through Ajax) with extra charaters?

I am working in a project. In which i am trying to get username from session created using the following code:-
GetCurrentUserInfo.java
package servlet;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.util.Vector;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class GetCurrentUserInfo extends HttpServlet
{
ServletContext contx = null;
public void init(ServletConfig config) throws ServletException
{
contx = config.getServletContext();
}
public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
{
try
{
OutputStream outer = res.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(outer);
String userName = (String) req.getSession().getAttribute("username");
oos.writeChars(userName);
oos.flush();
oos.close();
}
catch (Throwable e)
{
e.printStackTrace();
}
}
}
Calling.js
function getUserInfo()
{
var userInfoHttp;
if (window.XMLHttpRequest)
{
userInfoHttp = new XMLHttpRequest()
}
else if (window.ActiveXObject)
{
userInfoHttp = new ActiveXObject("Microsoft.XMLHTTP")
}
userInfoHttp.open("POST", "GetCurrentUserInfo", false);
userInfoHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
userInfoHttp.onreadystatechange = function ()
{
if (userInfoHttp.readyState == 4)
{
if (userInfoHttp.status == 200)
{
var res = TrimString(userInfoHttp.responseText);
alert(res);
}
}
}
userInfoHttp.send(null);
isAnnotationUpdate = false;
}
I res i am getting userName with some extra characters like this:- "���w�s�#�s�.�c�o�m"
In actual my userName is s#s.com only.
I think that 2 things can fix your encoding problem
Firstly use the OutputStreamWriter and give it encoding value
OutputStream stream = response.getOutputStream();
OutputStreamWriter writer = new OutputStreamWriter(stream, "UTF-8");
String userName=(String)req.getSession().getAttribute("username");
writer.write(userName);
writer.flush();
and then make sure your response has the correct encoding
response.setCharacterEncoding("UTF-8");
Related article : Unexpected character when downloading file client side from a servlet
UPDATE
And something else i forgot in original answer. Set the ContentTyoe of the response Object to text/plain because you are actually returning plain text chars
response.setContentType("text/plain");

Categories