I'm using the pushwoosh phonegap plugin for push notifications. After successful registration I need to store the device ID that the registration used in the "hwid" parameter so that I can target push notifications that I send with this same device ID. This works great on Android since it seems the phonegap device.uuid is the same ID that the pushwoosh plugin is sending to their servers. However, on ios the device.uuid returns a different ID than what is sent to pushwoosh. I can see from the Xcode console log the hwid that the plugin is sending to pushwoosh but cannot figure out where they are getting this ID from and how to access the same ID within phonegap.
EDIT: I was hoping the getRemoveNotificationStatus function would return this info but it actually returns less than the registerDevice callback.
UPDATE: Ok, from digging through their plugin code I see where they are constructing this ID that they send to their servers. Not sure why this ID isn't accessible through the phonegap plugin since this is the ID that I ultimately need to have in order to target a push notification to the specific device.
Their code:
(NSString *) uniqueDeviceIdentifier{
NSString *macaddress = [self macaddress];
NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
NSString *stringToHash = [NSString stringWithFormat:#"%#%#",macaddress,bundleIdentifier];
NSString *uniqueIdentifier = [self stringFromMD5:stringToHash];
return uniqueIdentifier;
}
- (NSString *) uniqueGlobalDeviceIdentifier{
// >= iOS6 return identifierForVendor
UIDevice *device = [UIDevice currentDevice];
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"6.1")) {
if ([device respondsToSelector:#selector(identifierForVendor)] && [NSUUID class]) {
NSUUID *uuid = [device identifierForVendor];
return [uuid UUIDString];
}
}
// Fallback on macaddress
NSString *macaddress = [self macaddress];
NSString *uniqueIdentifier = [self stringFromMD5:macaddress];
return uniqueIdentifier;
}
Are you sure that you need the hwid?
When I use the Pushwoosh Remote API to send push messages to individual devices I target using the "devices" tag and then just supply the deviceToken of the devices I wish to message.
The device token is easily accessible as it's part of the status-return from the plugin (status['deviceToken']).
As I posted here.
I found a work-around for anyone who needs this. Just open up the class "PWRequest.m" in xcode. Add the code below just under "[dict setObject:hwid forKey:#"hwid"];" in the NSMutableDictionary method.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"hwidfile2.txt"];
NSLog(#"From Echo Class File Path: %#", filePath);
NSString *str = hwid;
This will save a text file to your local app directory in which you can access from your Javascript code. For example, you can use this JS code to access and print the hwid to the console. Just call the 'readPwfile(filename)' function, passing in the name of your file as the function argument.
function readPWFile(fileName){
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fileSystem){
fileSystem.root.getFile(fileName, null, gotReadFileEntry, fail);
});
function gotReadFileEntry(fileEntry) {
fileEntry.file(gotFile, fail);
}
function gotFile(file){
//readDataUrl(file);
readAsText(file);
}
function readAsText(file) {
var reader = new FileReader();
reader.onloadend = function(evt) {
console.log('Reading file... hwig Result: '+evt.target.result);
};
reader.readAsText(file);
}
}
Related
being a Node newbie, I seem to be struggling with some very basic steps. Can someone point me in the right direction please?
Essentially, I'm trying to send an input from an iOS (Objective-C) client to a Node.js server, but somehow not able to parse the http message body. In fact the data being posted from the client is not even appearing in the request if I log the same in the POST API on the server. I can confirm the endpoints are correct since other logs are getting printed... Here's my iOS and Node code - seems to be pretty straightforward...
Appreciate your inputs...
iOS code:
- (IBAction)sendUsername:(id)sender
{
NSMutableURLRequest *postRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"http://MYURL:PORT/registerUser"]];
NSDictionary *sentData = [[NSDictionary alloc] initWithObjectsAndKeys:#"socool", #"username", nil];
NSError *theError = nil;
NSData *postData = [NSJSONSerialization dataWithJSONObject:sentData options:NSJSONWritingPrettyPrinted error:&theError];
[postRequest setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[postRequest setHTTPMethod:#"POST"];
[postRequest setHTTPBody:postData];
// Have tried with both - initWithRequest and with sendSyncRequest - both dont show the req.body on the server...
// NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:postRequest delegate:self];
NSError *returnedError = nil;
NSURLResponse *urlResponse = [[NSURLResponse alloc] init];
NSData *dataResponse = [NSURLConnection sendSynchronousRequest:postRequest returningResponse:&urlResponse error:&returnedError];
}
Node.js code:
app.post('/registerUser', function(req, res) {
console.log("Request to register new user received"); // This gets printed successfully...
body = [];
body = Buffer.concat(body).toString();
console.log("Targeted output is: ", req.body.username); // req.body itself keeps coming as undefined.
});
It looks like you're using ExpressJS. If that's the case, prior to setting up your route with app.post, did you specify a bodyParser?
Take a look at this: http://expressjs.com/en/api.html
Specifically, the 'req.body' section.
Express relies upon a middleware that is going to intercept the request, parse it, and then fill req.body with it.
I'm still a beginner with Objective C
I developed a website using cakephp and I used a paid api for the map
Now I'm trying to build an iOS app but they don't have an iOS api so I only need to display the map into WKWebView
I removed all the buttons and created native buttons
I succeed to to inject JS to the native buttons using evaluateJavaScript and it works fine
But now I created an UISeachBar on the navigation bar and I'm using
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
I want to send the searchText to a JS function and then return an array
the problem is that when I created a JS function just for testing I get this message when I type String :
Error Domain=WKErrorDomain Code=4 "A JavaScript exception occurred" UserInfo={NSLocalizedDescription=A JavaScript exception occurred}
But when I type numbers it works fine
My Objc code :
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
NSString *function = [[NSString alloc] initWithFormat: #"getSuggest(%#)", searchText];
[_webView evaluateJavaScript:function completionHandler:^(NSString *result, NSError *error)
{
NSLog(#"Error %#",error);
NSLog(#"Result %#",result);
}];
}
My JS code :
var getSuggest = function(searchText) {
return searchText;
}
you have to embed the searchText into "" for the js function call:
NSString *function = [[NSString alloc] initWithFormat: #"getSuggest(\"%#\")", searchText];
I'm using pushwoosh to send push notifications to my ios mobile app. I want to allow users to disable notifications from within the app. The problem I'm having is that the pushwoosh api uses a different device id for ios than it does for android. The device id is created by the plugin using native code. It uses the hardware mac address and applies the md5 algorithm to create a "unique" id that phonegap is calling "hwid"(hardware id). I've found the native, objective c class that does this but I don't know how to access the variable, "hwid", from Javascript.
I've read through the phonegap documentation and have created a plugin that allows me to access native ios classes. My problem is that I don't know objective c and therefore cannot figure out how to return the variable to the callback.
The pushwoosh api requires the device id in order to unregister a device as you can see here:
{
"request":{
"application":"APPLICATION_CODE",
"hwid": "hardware device id"
}
}
I have seen this post and it is not helpful for what I'm trying to accomplish. However, it does show the native code that creates the unique id.
I also found this class that prints the hwid to the console. If I could find a way to access the "hwid" below from my js code I would be all set.
#import "PWRequest.h"
#implementation PWRequest
#synthesize appId, hwid;
- (NSString *) methodName {
return #"";
}
//Please note that all values will be processed as strings
- (NSDictionary *) requestDictionary {
return nil;
}
- (NSMutableDictionary *) baseDictionary {
NSMutableDictionary *dict = [NSMutableDictionary new];
[dict setObject:appId forKey:#"application"];
[dict setObject:hwid forKey:#"hwid"];
NSLog(#"hwid: %#", hwid);
return [dict autorelease];
}
- (void) parseResponse: (NSDictionary *) response {
}
- (void) dealloc {
self.appId = nil;
self.hwid = nil;
[super dealloc];
}
#end
Can someone point me in the right direction? Thanks.
We have just added unregisterDevice method for iOS Phonegap Javascript.
PushNotification.prototype.unregisterDevice = function(success, fail) {
cordova.exec(success, fail, "PushNotification", "unregisterDevice", []);
};
It used to work only for Android, now it is available on iOS as well.
For Phonegap 3.0 please see the newest Pushwoosh plugin repo:
https://github.com/shaders/pushwoosh-phonegap-3.0-plugin
For older Phonegap versions <= 2.9 please see legacy Pushwoosh Phonegap plugin:
https://github.com/shaders/phonegap-cordova-push-notifications/tree/master/iOS
I hope it helps!
I found a work-around for anyone who needs this. Just open up the class "PWRequest.m" in xcode. Add the code below just under "[dict setObject:hwid forKey:#"hwid"];" in the NSMutableDictionary method.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"hwidfile2.txt"];
NSLog(#"From Echo Class File Path: %#", filePath);
NSString *str = hwid;
This will save a text file to your local app directory in which you can access from your Javascript code. For example, you can use this JS code to access and print the hwid to the console. Just call the 'readPwfile(filename)' function, passing in the name of your file as the function argument.
function readPWFile(fileName){
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fileSystem){
fileSystem.root.getFile(fileName, null, gotReadFileEntry, fail);
});
function gotReadFileEntry(fileEntry) {
fileEntry.file(gotFile, fail);
}
function gotFile(file){
//readDataUrl(file);
readAsText(file);
}
function readAsText(file) {
var reader = new FileReader();
reader.onloadend = function(evt) {
console.log('Reading file... hwig Result: '+evt.target.result);
};
reader.readAsText(file);
}
}
I'm trying to download a file programmly on this site, and I found that when you click the highlighted download button("下载"), it runs a Javascript: document.getElementById('downLoad').action='/download.php?fileid=11024011';downishare('0');
On my Mac, it runs fine and downloads the file when I run it on Safari. But when I use
[webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:#"document.getElementById('downLoad').action='/download.php?fileid=11024011'"]];
It doesn't return anything.
Does anyone know why and how can I get the download URL?
Thanks.
Well... the download url is this: http://ishare.iask.sina.com.cn/download.php?fileid=11024011
You can check it also with the 'Network' tab in chrome or firebug in firefox. BUT... when you try to access it directly, it redirects you. There might be some server side validation of the request, like the referrer url or something.
Have you tried implementing the webView delegate method shouldStartLoadWithRequest to parse through links?
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
if ([[[request URL] absoluteString] hasPrefix:#"http://ishare.iask.sina.com.cn/download.php?fileid="])
//I believe this would download everything that has a link prefix of "http://ishare.iask.sina.com.cn/download.php?fileid="
//So you should create some sort of checker to make sure it only downloads the file they select
// Determile cache file path
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *filePath = [NSString stringWithFormat:#"%#/%#", [paths objectAtIndex:0],#"index.html"];
// Download and write to file
NSURL *url = [NSURL URLWithString:[[request URL] absoluteString]];
NSData *urlData = [NSData dataWithContentsOfURL:url];
[urlData writeToFile:filePath atomically:YES];
// Load file in UIWebView
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:filePath]]];
return NO;
}
else {
return YES;
}
<script language="javascript">
alert("Hell! UIWebView!");
</script>
I can see the alert message inside my UIWebView but can I handle this situation?
Update:
I'm loading a web-page into my UIWebView:
- (void)login {
NSString *requestText = [[NSString alloc] initWithFormat: #"%#?user=%#&password=%#", DEFAULT_URL, user.name, user.password]; // YES, I'm using GET request to send password :)
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:requestText]];
[webView loadRequest:request];
}
The target page contain a JS. If user name or password is incorrect this JS show alert.
I have not any access to its sources.
I want to handle it inside my UIWebViewDelegate.
A better solution to this problem is to create a Category for UIWebView for the method
webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:
So that you can handle the alert event in any way that you'd like. I did this because I don't like the default behavior of UIWebView when it puts the filename of the source in the UIAlertView title. The Category looks something like this,
#interface UIWebView (JavaScriptAlert)
- (void)webView:(UIWebView *)sender runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame;
#end
#implementation UIWebView (JavaScriptAlert)
- (void)webView:(UIWebView *)sender runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame {
UIAlertView* dialogue = [[UIAlertView alloc] initWithTitle:nil message:message delegate:nil cancelButtonTitle:#"Okay" otherButtonTitles:nil];
[dialogue show];
[dialogue autorelease];
}
#end
This seems to do it:
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
JSContext *ctx = [webView valueForKeyPath:#"documentView.webView.mainFrame.javaScriptContext"];
ctx[#"window"][#"alert"] = ^(JSValue *message) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"JavaScript Alert" message:[message toString] delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
};
}
Note: only tested on iOS 8.
If by "contain a flash" you mean the page you're loading into your web view has an Adobe Flash movie in it, you're out of luck, I'm afraid. Mobile Safari doesn't support Flash, and most likely never will.
In the general case, if you want JavaScript running in a web view to communicate with the native app hosting it, you can load fake URLs (for example: "myapp://alert?The+text+of+the+alert+goes+here."). That will trigger the webView:shouldStartLoadWithRequest:navigationType: delegate method. In that method, inspect the request, and if the URL being loaded is one of these internal communications, trigger the appropriate action in your app, and return NO.