For a personal project of mine, I'm trying to retrieve iPhone WiFi signal strength. I'm fully aware that this in the land of undocumented goodness, so please refrain from the "No Appstore" answers. :)
Anywho, I've been reading up on previous WiFi Network Scanner Apps (WiFi Stumbler), but I'm afraid most (if not all) reflect outdated SDK documentation. Hopefully, this question will also provide some centralized / insightful material with the most recent iPhone SDK 3.1.2.
Here's my incomplete/not-working code:
.h
void *libHandle;
void *airportHandle;
int (*open)(void *);
int (*bind)(void *, NSString *);
int (*close)(void *);
int (*scan)(void *, NSArray **, void *);
.m
libHandle = dlopen("/System/Library/PrivateFrameworks/MobileWiFi.framework/MobileWiFi",RTLD_LAZY);
open = dlsym(libHandle, "Apple80211Open");
bind = dlsym(libHandle, "Apple80211BindToInterface");
close = dlsym(libHandle, "Apple80211Close");
scan = dlsym(libHandle, "Apple80211Scan");
open(&airportHandle);
bind(airportHandle, #"en0");
NSLog(#"Result %#",libHandle);
When executed on the device, it'll produce my ever-so-favorite...
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
I'm thinking the dynamic loading call, isn't loading anything. The directory: /System/Library/PrivateFrameworks/ only lists a Info.plist file with no binaries or aliases.
Probably doing something terribly wrong (wrong directory?)... appreciate any help!
Also, as a follow up. To extract the WiFi information, it might be done by:
GetInfoCopy = dlsym(libHandle, "Apple80211GetInfoCopy");
And my questions are 1) Has anybody had any luck with this? 2) How do you get a header dump like I would using with class-dump on Objective-C libraries (because MobileWifi is in C)?
For anybody who stumbles upon this question, here's my library to access 802.11 networks. Although Apple claims to deny any applications that use private frameworks, there are several closed-sourced WiFi applications on the AppStore. Use at your own risk.
This library works with iPhone SDK 3.1.2.
SOLStumbler.h
SOLStumbler.m
Use:
SOLStumbler *networksManager = [[SOLStumbler alloc] init];
[networksManager scanNetworks];
Result:
An networks NSDictionary of a info NSDictionary.
Use CFShow to explore the returned pointer containing information. Or call the description method for sample output.
Update as of July 2012 (iOS 5.0)
The code you're trying to use is pretty old. This stuff (e.g. WiFiManager or MobileWiFi) is in a private framework. That means Apple can, and often will, change it or move if from OS version to version.
I ran nm on the MobileWifi framework, and didn't see any of those function names. So, I think that's why your code fails.
$ pwd
/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/PrivateFrameworks/MobileWiFi.framework
$ nm MobileWiFi | grep 80211
$
I suppose it might be necessary to run nm on the actual device framework, but I didn't waste my time, after looking at this:
Discussion of this framework, and follow-ons.
It looks like you can now find equivalent (?) functions in the IPConfiguration framework. Try this code:
libHandle = dlopen("/System/Library/SystemConfiguration/IPConfiguration.bundle/IPConfiguration", RTLD_LAZY);
I ran it on a jailbroken iOS 5.0.1 phone and it worked (loaded the dylib and found a few of the Apple80211 functions). From that thread I linked to, it looks like you may need to have this installed in /Applications on a jailbroken phone, in order to work fully. Or, possibly have to mess around with adding some entitlements to your sandboxed app.
These Apple80211xxx functions do not exist in MobileWiFi.framework (you can check using the `nm' tool against the SDK binaries).
(Also, it's impossible to dump a C header from binaries because all type information are removed during compilation. You need to reverse engineer it yourself or wait for someone to do so.)
I'm not sure if this would be a problem, but open/close/bind are names that are already in-use (standard C library).
The binary doesn't exist, as it is stored in the dyld shared_cache (dlopen will succeed because the library is technically 'loaded.'); however, I note that you're not checking that any of libHandle, open, close, bind or scan are valid when you retrieve them from the dl* functions.
Related
I'm attempting to create an iOS 5 app with some very basic FTP functionality and need some guidance. It will be connecting to a device on a local network and performing read/write actions with .dat/txt files. I've done some searching for the past few days and have seen various recommendations but nothing simple enough that I can pick up and quickly modify for my personal use.
My questions are these:
Are there any tutorials/sample code that you could recommend to me?
What frameworks and classes should I be working with for basic read/write operations?
Lastly, I should mention that I have given a considerable amount of time to analyzing the SimpleFTPSample from Apple but the sample code is giving "Connection Failure" and "Stream Open Error" notices for each example, so I'm a bit wary of its usefulness.
Forgive me if this has been answered elsewhere. All of the related posts have pieces of the answer I need, but not the whole thing. Thank you in advance!
EDIT for clarity: A well-defined example or step-by-step tutorial is what I would really like. My own Google searches have turned up nothing and I am desperately in need of some guidance here.
UPDATE:
I posted this question long ago but have continued using the FTPHelper mentioned in the accepted answer. I recently brushed the dust off the old project and realized there was a minor memory leak in FTPHelper's fetch function that can be an app-killer if called repeatedly. If anybdy stumbles across this question and chooses to use FTPHelper, be sure to add the CFRelease line seen in the code below.
- (void) fetch: (NSString *) anItem
{
if (!self.uname || !self.pword) COMPLAIN_AND_BAIL(#"Please set user name and password first");
if (!self.urlString) COMPLAIN_AND_BAIL(#"Please set URL string first");
NSString *ftpRequest = [NSString stringWithFormat:#"%#/%#", self.urlString, [anItem stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
/* CFShow(ftpRequest); */
NSString *writepath = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
self.filePath = [writepath stringByAppendingPathComponent:anItem];
CFURLRef writeURL = CFURLCreateFromFileSystemRepresentation (NULL, (const UInt8 *) [writepath UTF8String], [writepath length], NO);
MySimpleDownload((CFStringRef)ftpRequest, writeURL, (CFStringRef) self.uname, (CFStringRef)self.pword);
CFRelease(writeURL);//ADD THIS LINE TO FIX MEMORY LEAK
}
The SimpleFTPSample app is running perfect, probably there is an issue that you can't see. What I can recommend you (except Apple's example) is to check THIS example which contains a helper class for all basic FTP operations. One thing to be aware of is iOS 5 ARC. Both Apple's example and the one I linked are for older iOS versions.
There are basically 2 ways to use them in iOS 5 - by telling the compiler to not use ARC by adding -fno-objc-arc flag in [Your project] -> TARGETS -> [Your app] -> Build Phases -> Compile Sources -> [Your file], or by using the built-in tool in Xcode for converting to ARC.
I personally have tested only the first method and it works for me.
If this does not help you I can write an example, but unfortunately today I am very busy.
UPDATED:
The basic mechanism is to use [FTPHelper list:THE_FTP_URL] to list the content of a folder, then create one list with the content and depending on the type (file or folder) download using [FTPHelper download: THE_FTP_URL_WITH_THE_FILENAME_FROM_LISTING]. From here you have to implement
- (void) downloadFinished
{
//do the reading depending on the file type
NSData *data = [NSData dataWithContentsOfFile:[FTPHelper sharedInstance].filePath];
}
The uploading is achieved in a similar way - using [FTPHelper upload:FILE_TO_UPLOAD] with a file from the filesystem.
There are many libraries which you could use and they are working great. :)
For example:
http://www.chilkatsoft.com/ftp-objc.asp
http://code.google.com/p/ios-ftp-server/
I recommend using them, because coding one by yourself would take a lot of time :)
One thing to remember, as o15a3d4l11s2 said, is to be aware of ARC. If you use it don't forget to add build flags to libraries which aren't ARC.
My goal is to use libphonenumber, google's phone number handling library for an iPhone project I'm working on.
After downloading it (and many many hours), I complied the C++ version of the library, and it built a number ".a" files and ".dylib" files, of which I assumed I must import into my xCodeProject in order to access those C++ functions.
So I imported "libphonenumber.a" into my project, updated my target, build settings, build phases, and Library Search Paths as needed.
Building the xCode project for Device & Simulator pass, however give me the following warning:
"ld: warning: ignoring file ../XcodeProjects/libphonenumber/build/libphonenumber.dylib, file was built for unsupported file format which is not the architecture being linked (armv7)". (or i386 when compiling for simulator)
I understand from this that I must compile the libphonenumber for the correct i386 and/or armv7 architecture. So I tried to do that, but quickly realized this requires me to also rebuild libphonenumber's 3 dependent libraries as well, for the i386/armv7 architectures in order for libphonenumber's to now properly compile. Eventually, I gave up on that, it started to look like a big mess ahead of me.
After all my trials, I'm left with
3 Questions:
1) How to I compile libphonenumber C++ library for use with i386/armv6/armv7 architectures.
2) When using a c++ library, is my assumption correct? Is it a matter of simply importing the ".a" file that results from the compilation, and just point to it in the header of my xCode project files? What exactly are the steps for including and using c++ libraries and accessing their functions from objective-c inside xCode?
3) I did find LPNKit, an objective-c port for libphonenumber, however it is incomplete. Has anyone heard of it, and had any luck using it? Or does anyone have an objective-c port for libphonenumber that is complete, working, with instructions on how to compile and install it correctly?
Any help or advice on how to get this library working on iOS would be greatly appreciated.
Update:
I ended up using the javascript version of libphonenumber, adding all the files to my bundle, including all referenced javascript libraries and using UIWebview and stringByEvaluatingJavaScriptFromString to run functions. You could also have the UIWebview reference the javascript library online (I just preferred to have everything local as not to depend on an internet connection).
Here is a sample of what I did:
webView_ = [[UIWebView alloc] init];
[webView_ loadHTMLString:
#"<script src='base.js'></script>"
"<script>"
"goog.require('goog.dom');"
"goog.require('goog.json');"
"goog.require('goog.proto2.ObjectSerializer');"
"goog.require('goog.string.StringBuffer');"
"</script>"
"<script src=\"phonemetadata.pb.js\"></script>"
"<script src=\"phonenumber.pb.js\"></script>"
"<script src=\"metadata.js\"></script>"
"<script src=\"phonenumberutil.js\"></script>"
"<script src=\"asyoutypeformatter.js\"></script>"
"<script src=\"normalize.js\"></script>"
baseURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] resourcePath]]];
NSString *function = [[NSString alloc] initWithFormat: #"phoneNumberParser('%#','%#','')", phoneNumber, ISOCountryCode];
NSLog(#"function is: %#", function);
NSString *result =[webView_ stringByEvaluatingJavaScriptFromString:function];
The result variable gets me the formatted number.
I hope that helps anyone who ran into the same issue I did.
It has been ported by our team.
You can find it https://github.com/me2day/libPhoneNumber-iOS
Just note that libphonenumber Javascript library includes Google's closure library.
So you should consider, wrapping your Javascript call in a Javascript object and then compile it using closure builder in order to get an efficient and light weight script. (closure library before compilation : 18Mb, after compilation 300Kb !)
See above a sample of such a wrapper
goog.provide('sphone.phonenumber');
goog.require('goog.dom');
goog.require('goog.json');
goog.require('goog.proto2.ObjectSerializer');
goog.require('goog.array');
goog.require('goog.proto2.PbLiteSerializer');
goog.require('goog.string');
goog.require('goog.proto2.Message');
goog.require('goog.string.StringBuffer');
goog.require('i18n.phonenumbers.NumberFormat');
goog.require('i18n.phonenumbers.PhoneNumber');
goog.require('i18n.phonenumbers.PhoneNumberUtil');
sphone.phonenumber = function(phoneNumber, regionCode) {
this.getCountryCallCode=phonenumberGetCountryCallCode;
};
function phonenumberGetCountryCallCode(phoneNumber, regionCode) {
var phoneUtil = i18n.phonenumbers.PhoneNumberUtil.getInstance();
var number = phoneUtil.parseAndKeepRawInput(phoneNumber, regionCode);
return number.getCountryCode();
};
// Ensures the symbol will be visible after compiler renaming.
goog.exportSymbol('sphone.phonenumber', sphone.phonenumber);
1) Fix all the errors and re-compile all the dependencies for arm. As you said before.
2) Yes. According to kstenerud’s iOS-Universal-Framework
Using an iOS Framework
iOS frameworks are basically the same as regular dynamic Mac OS X frameworks, except they are statically linked.
To add a framework to your project, simply drag it into your project. When including headers from your framework, remember to use angle bracket syntax rather than quotes.
For example, with framework "MyFramework":
#import <MyFramework/MyClass.h>
This question Importing an external library in xcode - C++ follows like this: Import C++ library, use it, get errors from its dependency on built-in frameworks, import those built-in frameworks, everything works.
3) I would invest in LPNKit instead of fighting your way through option 1. You can both contribute and benefit from LPNKit. GitHub is a wonderful place and the great boost of this over option 1 is that you have another person (or people!) who have the same goal and will all work together to achieve it.
I've been using http://code.google.com/p/plblocks/ for a while now to get blocks support in our 3.2 iPad app. It was recently pointed out to me that you can set xcode to use the 4.0 SDK, then set the OS Deployment target to 3.2.
If I do, the following code works.
void (^world)() = ^ {
NSLog(#"Hello World");
};
NSLog(#"Hello?");
world();
However, any time I sent a message to a block I get an EXC_BAD_ACCESS. For example, if I add the following line:
void (^acopy)() = [world copy];
This is a problem, since you have to copy blocks in order for them to keep their scope around later. Any idea why blocks would work, but the messages wouldn't? Am I missing some setting or something? Am I mistaken about the need to copy?
It seems you can still use Block_copy(). I don't know why PLBlocks would be able to use the Objective-C and the built-in compilers can't.
Here's an intro article:
http://developer.apple.com/mac/articles/cocoa/introblocksgcd.html
It says:
Importantly, block objects are laid
out in such a way that they are also
Objective-C objects if that runtime is
present.
I can't really see how you could be developing an iPad app without the Objective-C runtime present. As a sanity check you could make sure the C version (Block_copy()) works.
I am working on an iPhone application and would really like to determine if the device is roaming so that I can intelligently avoid costing my users expensive connections if out of their home network.
The application I am writing is for jailbroken phones, however I would prefer to use standard SDKs if possible.
Here is what I've already found:
1. Apple SDKs:
In the apple documentation, I found the promise in Apple's SCNetworkReachability API. The API provides access to such things as whether you are on a WIFI or a cell phone network, whether a network connection is currently established, etc. However searching the SCNetworkReachability API reference pdf for 'roam' or 'roaming' both turn up nil. So does their sample code.
2. Grep of a Jailbroken iPhone FS:
The preferences -> general -> networking tab is where users can turn on or off their roaming. Looking in the plist file for this ("/Applications/Preferences/Network.plist") I was able to find the following references:
PostNotification = "com.apple.commcenter.InternationalRoamingEDGE.changed";
cell = PSSwitchCell;
default = 1;
defaults = "com.apple.commcenter";
key = InternationalRoamingEDGE;
label = "EDGE_ROAMING_TOGGLE";
requiredCapabilities = (
telephony
);
This is certainly a lead, as it appears I can sign up for notifications that the user has changed the InternationalRoaming settings. Still, I'm not certain how to turn this into the knowledge that they are in fact, presently roaming.
3. Check the class dumped sources of SpringBoard:
I've dumped the classes of SpringBoard using class-dump. I was unable to find any references to 'roam' or 'roaming'
4. Obviously I started by checking at SO for this:
Couldn't find anything related.
Further steps: Does anyone have any advice here?
I know this is possible. Apple clearly has made it very difficult to find however. I highly doubt this is possible without using a private framework. (such as CoreTelephony). As this is a jailbroken app, I may resort to screen-scraping the the carrier name with injected code in the SpringBoard, but I would really rather prefer not to go that route. Any advice much appreciated. Thanks.
There is! It's not documented at all, and I highly doubt this would work on a non-jailbroken phone (as it requires using files not in the sandbox). However, here is how it is done.
The iPhone file system keeps two softlinks:
static NSString *carrierPListSymLinkPath = #"/var/mobile/Library/Preferences/com.apple.carrier.plist";
static NSString *operatorPListSymLinkPath = #"/var/mobile/Library/Preferences/com.apple.operator.plist";
when these links are pointing at the same file, the telephone is not roaming. When pointing at different files, the telephone is romaing.
Simplified code (no error checking, etc):
- (BOOL)isRoaming
{
NSFileManager *fm = [NSFileManager defaultManager];
NSError *error;
NSString *carrierPListPath = [fm destinationOfSymbolicLinkAtPath:carrierPListSymLinkPath error:&error];
NSString *operatorPListPath = [fm destinationOfSymbolicLinkAtPath:operatorPListSymLinkPath error:&error];
return (![operatorPListPath isEqualToString:carrierPListPath]);
}
the solution of the symlinks are not the only way to do it but definitely it is the best. As I just realized, the Strings returned contains the MCC and MNC codes of the operator and carrier!!! Even the core telephony framework is not able to retrieve those informations about the operator your iPhone is attached when in roaming.
Logs:
carrier: /System/Library/Carrier Bundles/iPhone/72410/carrier.plist
operator: /System/Library/Carrier Bundles/iPhone/20810/carrier.plist
As you can see, the carrier (original cellular provider) line contains the file inside the "folder" 72410, which means MCC 724 (Brazil) and MNC 10 (VIVO).
The operator (actually the one my cell phone is attached now - i'm in roaming) is inside the folder 20810, which means MCC 208 (France) and MNC 10 (SFR).
By the way, I'm using iPhone 4 with iOS5.
On a non-jailbreak device you can use third party services like http://ipinfo.io (my own service) to find out the current country of even carrier code based on the device's IP address, and you can then compare that to the CTCarrier details to determine if the device is roaming. Here's the standard ipinfo.io API response:
$ curl ipinfo.io/24.32.148.1
{
"ip": "24.32.148.1",
"hostname": "doc-24-32-148-1.pecos.tx.cebridge.net",
"city": "Pecos",
"region": "Texas",
"country": "US",
"loc": "31.3086,-103.5892",
"org": "AS7018 AT&T Services, Inc.",
"postal": "79772"
}
Custom packages are available that also include the mnc/mcc details of mobile IPs though. See http://ipinfo.io/developers for details.
I need to write some code that will let me query a m4a file and extract the chapter information out. Including:
chapter name
chapter start time
chapter artwork
I did some quick searching and it seems this is viewed as proprietary information by Apple? I found some discussions, but most were from 2005. Also there have been some similar questions on here, but more for CREATING m4a files with chapters, not querying.
Is this just something I have to DIY, cause there isn't a nice apple API for me to use? Or am I missing something obvious?
Also, ideally I need whatever technique I end up using to work on the iPhone.
The metadata tags system is Apple-proprietary. To work with the tags, you have to (sigh) reverse-engineer it or work with a library that has already done this.
I found the following links, but honestly it seems like you will have to pull out the hex editor.
Binary format info (basic spec for generic tags)
Perl library for working with M4A files.
Turns out this is much simpler than talked about here in the "answers". Not sure if this works on the iPhone, but I just tested it in a command line app:
QTMovie* movie = [QTMovie movieWithFile:#"filename.m4a" error:nil];
NSInteger numChapters = [movie chapterCount];
NSLog(#"Number of Chapters: %d", numChapters);
NSArray* chapterArray = [movie chapters];
for ( NSDictionary* chapDict in chapterArray )
{
NSLog(#"%#", [chapDict objectForKey:#"QTMovieChapterName"] );
}
Easy as pie. DOH!
this library should solve your needs, but is not runnable on iphone without jailbreaking I would think. http://wmptagext.sourceforge.net/
oops if you need it to work on iphone there is probably an apple api to get this info. /me looks
it sounds like you need to play around with the ipodlibrary library....
http://developer.apple.com/iphone/library/documentation/Audio/Conceptual/iPodLibraryAccess_Guide/UsingTheiPodLibrary/UsingTheiPodLibrary.html#//apple_ref/doc/uid/TP40008765-CH101-SW1
If the files in question live in the iPod library,
maybe you can get your information via the MPMediaLibrary
query interface (3.0 upward).