SCNetworkReachabilityCallBack has a C pointer to a user-specified info. Does that info guarantee to point to the same context object that was passed in SCNetworkReachabilitySetCallback's context parameter?
Boolean SCNetworkReachabilitySetCallback (
SCNetworkReachabilityRef target,
SCNetworkReachabilityCallBack callout,
SCNetworkReachabilityContext *context
);
typedef void (*SCNetworkReachabilityCallBack) (
SCNetworkReachabilityRef target,
SCNetworkReachabilityFlags flags,
void *info
);
SCNetwortReachability reference
It points to the info field of the context structure that you associated with that particular SCNetworkReachabilityRef.
typedef struct {
CFIndex version;
void * info;
const void *(*retain)(const void *info);
void (*release)(const void *info);
CFStringRef (*copyDescription)(const void *info);
} SCNetworkReachabilityContext;
Related
I need to obtain MCC and MNC code for the current country (NOT from the class CTCarrier for the SIM home country).
I use private API for CoreTelephony.framework. On the my device all works correct. But on the other devices in the method CellMonitorCallback we obtain cells = NULL.
May be somebody can help what I done wrong?
#import "AMCoreTelephone.h"
#import <CoreTelephony/CTCarrier.h>
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
struct CTResult
{
int flag;
int a;
};
extern CFStringRef const kCTCellMonitorCellType;
extern CFStringRef const kCTCellMonitorCellTypeServing;
extern CFStringRef const kCTCellMonitorCellTypeNeighbor;
extern CFStringRef const kCTCellMonitorCellId;
extern CFStringRef const kCTCellMonitorLAC;
extern CFStringRef const kCTCellMonitorMCC;
extern CFStringRef const kCTCellMonitorMNC;
extern CFStringRef const kCTCellMonitorUpdateNotification;
id _CTServerConnectionCreate(CFAllocatorRef, void*, int*);
void _CTServerConnectionAddToRunLoop(id, CFRunLoopRef, CFStringRef);
mach_port_t _CTServerConnectionGetPort(id);
#ifdef __LP64__
void _CTServerConnectionRegisterCallService(id);
void _CTServerConnectionUnregisterCallService(id,int*);
void _CTServerConnectionRegisterForNotification(id, CFStringRef);
void _CTServerConnectionCellMonitorStart(id);
void _CTServerConnectionCellMonitorStop(id);
void _CTServerConnectionCellMonitorCopyCellInfo(id, void*, CFArrayRef*);
void _CTServerConnectionIsInHomeCountry(id, void*, int*);
void _CTServerConnectionCopyCountryCode(id, void*, CFStringRef);
#else
void _CTServerConnectionRegisterCallService(struct CTResult*, id);
#define _CTServerConnectionRegisterCallService(connection) { struct CTResult res; _CTServerConnectionRegisterCallService(&res, connection); }
void _CTServerConnectionRegisterForNotification(struct CTResult*, id, CFStringRef);
#define _CTServerConnectionRegisterForNotification(connection, notification) { struct CTResult res; _CTServerConnectionRegisterForNotification(&res, connection, notification); }
void _CTServerConnectionCellMonitorStart(struct CTResult*, id);
#define _CTServerConnectionCellMonitorStart(connection) { struct CTResult res; _CTServerConnectionCellMonitorStart(&res, connection); }
void _CTServerConnectionCellMonitorStop(struct CTResult*, id);
#define _CTServerConnectionCellMonitorStop(connection) { struct CTResult res; _CTServerConnectionCellMonitorStop(&res, connection); }
void _CTServerConnectionCellMonitorCopyCellInfo(struct CTResult*, id, void*, CFArrayRef*);
#define _CTServerConnectionCellMonitorCopyCellInfo(connection, tmp, cells) { struct CTResult res; _CTServerConnectionCellMonitorCopyCellInfo(&res, connection, tmp, cells); }
void _CTServerConnectionIsInHomeCountry(struct CTResult*, id, int*);
#define CTServerConnectionIsInHomeCountry(connection, isHomeCountry) { struct CTResult res; _CTServerConnectionIsInHomeCountry(&res, connection, &isHomeCountry); }
#endif
#implementation AMCoreTelephone
{
CTCarrier *_carrier;
id CTConnection;
mach_port_t port;
}
+ (instancetype) sharedInstance
{
static AMCoreTelephone *instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[AMCoreTelephone alloc] init_true];
});
return instance;
}
- (instancetype) init_true
{
if (self = [super init]) {
_carrier = [[CTTelephonyNetworkInfo new] subscriberCellularProvider];
}
return self;
}
- (void) startMonitoring{
#if TARGET_IPHONE_SIMULATOR
return;
#else
CTConnection = _CTServerConnectionCreate(kCFAllocatorDefault, CellMonitorCallback, NULL);
_CTServerConnectionRegisterForNotification(CTConnection, kCTCellMonitorUpdateNotification);
port = _CTServerConnectionGetPort(CTConnection);
CFMachPortRef ref = CFMachPortCreateWithPort(kCFAllocatorDefault,port,NULL,NULL, NULL);
CFRunLoopSourceRef rlref = CFMachPortCreateRunLoopSource ( kCFAllocatorDefault, ref, 0);
CFRunLoopRef currentRunLoop = CFRunLoopGetCurrent();
CFRunLoopAddSource(currentRunLoop, rlref, kCFRunLoopCommonModes);
_CTServerConnectionCellMonitorStart(CTConnection);
#endif
}
- (void) stopMonitoring{
_CTServerConnectionCellMonitorStop(CTConnection);
}
int CellMonitorCallback(id connection, CFStringRef string, CFDictionaryRef dictionary, void *data)
{
int tmp = 0;
CFArrayRef cells = NULL;
_CTServerConnectionCellMonitorCopyCellInfo(connection, (void*)&tmp, &cells);
if (cells == NULL)
{
return 0;
}
for (NSDictionary* cell in (__bridge NSArray*)cells)
{
int LAC, CID, MCC, MNC;
if ([cell[(__bridge NSString*)kCTCellMonitorCellType] isEqualToString:(__bridge NSString*)kCTCellMonitorCellTypeServing])
{
LAC = [cell[(__bridge NSString*)kCTCellMonitorLAC] intValue];
CID = [cell[(__bridge NSString*)kCTCellMonitorCellId] intValue];
MCC = [cell[(__bridge NSString*)kCTCellMonitorMCC] intValue];
MNC = [cell[(__bridge NSString*)kCTCellMonitorMNC] intValue];
}
else if ([cell[(__bridge NSString*)kCTCellMonitorCellType] isEqualToString:(__bridge NSString*)kCTCellMonitorCellTypeNeighbor])
{
}
}
CFRelease(cells);
return 0;
}
#end
I think the problem is using private api, so you can't run your app on non jailbreak phones. I'm researching the thing as same you but a little late :) and I found this answer to work on iOS 8.3, it says
As of iOS 8.3 all of the above solutions require entitlement to work
<key>com.apple.CommCenter.fine-grained</key>
<array>
<string>spi</string>
</array>
Also this project on github is only sample code for me that I can find.
I think you already know answer but this may helps someone else, because it's hard to find :)
As of iOS 8.3 all of the above solutions require entitlement to work
<key>com.apple.CommCenter.fine-grained</key>
<array>
<string>spi</string>
</array>
Indeed, tha above code mentioned is said that can be run to get the lac and cell on ios 8.3 and above. But I really don't know how to insert the above on a jailbroken phone. Could anyone give any detail information. Or anyone test this way ?
The error while creating a button in opencv
argument of type 'void (Window::)(int, void*)' does not match 'cv::ButtonCallback {aka void ()(int, void)}'
class Window{
void ChecKBox(int state, void* val){
// do nothing for now
return;
}
public:
void createCheckbox(){
cv::createButton(checkboxname, CheckBox, NULL, CV_CHECKBOX, 0);
}
};
int main(){
Window w;
w.createCheckBox();
}
I can't seem to find the fix to this problem.
oh, you can't pass in a member function of a class here. think of it, where would the 'this' pointer come from ? (like you call class members like w.CheckBox(1,NULL); there is no 'w' here. )
the highgui interface is a bit limited. it can only call free functions or static members.
so, if your callback function does not need anything from Window, make it static:
class Window {
static void CheckBox(int state, void* val) { /*you can't use 'this' here!*/ return; }
public:
void createCheckBox() { cv::createButton(checkboxname, CheckBox, NULL, CV_CHECKBOX, 0); }
};
int main() {
Window w;
w.createCheckBox();
}
I need to retrieve CellID, MCC, MNC, LAC and Network (GSM, 3G) of the current Serving Cell Tower in iOS 5.1 (iPhone 4S). I know this information is available because I can see it in FieldTest Mode (accessible after calling ****3001#12345#****). I suppose it to be accessible via Private/Undocumented iOS Frameworks.
In the question iphone, check values of cellId / Lac the author indicates I can get radio Informations cellId, Lac, MNC, MCC on iOS, but no information on how to do this is provided.
Can anybody tell me how to get this info?
I know three ways on how you can do it on iOS 5.x - 7.x. All of them use private APIs from CoreTelephony.framework. Supports both GSM and UMTS.
1) Using cell monitor
struct CTResult
{
int flag;
int a;
};
extern CFStringRef const kCTCellMonitorCellType;
extern CFStringRef const kCTCellMonitorCellTypeServing;
extern CFStringRef const kCTCellMonitorCellTypeNeighbor;
extern CFStringRef const kCTCellMonitorCellId;
extern CFStringRef const kCTCellMonitorLAC;
extern CFStringRef const kCTCellMonitorMCC;
extern CFStringRef const kCTCellMonitorMNC;
extern CFStringRef const kCTCellMonitorUpdateNotification;
id _CTServerConnectionCreate(CFAllocatorRef, void*, int*);
void _CTServerConnectionAddToRunLoop(id, CFRunLoopRef, CFStringRef);
#ifdef __LP64__
void _CTServerConnectionRegisterForNotification(id, CFStringRef);
void _CTServerConnectionCellMonitorStart(id);
void _CTServerConnectionCellMonitorStop(id);
void _CTServerConnectionCellMonitorCopyCellInfo(id, void*, CFArrayRef*);
#else
void _CTServerConnectionRegisterForNotification(struct CTResult*, id, CFStringRef);
#define _CTServerConnectionRegisterForNotification(connection, notification) { struct CTResult res; _CTServerConnectionRegisterForNotification(&res, connection, notification); }
void _CTServerConnectionCellMonitorStart(struct CTResult*, id);
#define _CTServerConnectionCellMonitorStart(connection) { struct CTResult res; _CTServerConnectionCellMonitorStart(&res, connection); }
void _CTServerConnectionCellMonitorStop(struct CTResult*, id);
#define _CTServerConnectionCellMonitorStop(connection) { struct CTResult res; _CTServerConnectionCellMonitorStop(&res, connection); }
void _CTServerConnectionCellMonitorCopyCellInfo(struct CTResult*, id, void*, CFArrayRef*);
#define _CTServerConnectionCellMonitorCopyCellInfo(connection, tmp, cells) { struct CTResult res; _CTServerConnectionCellMonitorCopyCellInfo(&res, connection, tmp, cells); }
#endif
...
id CTConnection = _CTServerConnectionCreate(NULL, CellMonitorCallback, NULL);
_CTServerConnectionAddToRunLoop(CTConnection, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
_CTServerConnectionRegisterForNotification(CTConnection, kCTCellMonitorUpdateNotification);
_CTServerConnectionCellMonitorStart(CTConnection);
int CellMonitorCallback(id connection, CFStringRef string, CFDictionaryRef dictionary, void *data)
{
int tmp = 0;
CFArrayRef cells = NULL;
_CTServerConnectionCellMonitorCopyCellInfo(connection, (void*)&tmp, &cells);
if (cells == NULL)
{
return 0;
}
for (NSDictionary* cell in (NSArray*)cells)
{
int LAC, CID, MCC, MNC;
if ([cell[(NSString*)kCTCellMonitorCellType] isEqualToString:(NSString*)kCTCellMonitorCellTypeServing])
{
LAC = [cell[(NSString*)kCTCellMonitorLAC] intValue];
CID = [cell[(NSString*)kCTCellMonitorCellId] intValue];
MCC = [cell[(NSString*)kCTCellMonitorMCC] intValue];
MNC = [cell[(NSString*)kCTCellMonitorMNC] intValue];
}
else if ([cell[(NSString*)kCTCellMonitorCellType] isEqualToString:(NSString*)kCTCellMonitorCellTypeNeighbor])
{
}
}
CFRelease(cells);
return 0;
}
2) Using CTTelephonyCenter
kCTRegistrationCellChangedNotification is sent every time current serving cell tower is changed.
extern CFStringRef const kCTRegistrationCellChangedNotification;
extern CFStringRef const kCTRegistrationGsmLac;
extern CFStringRef const kCTRegistrationLac;
extern CFStringRef const kCTRegistrationGsmCellId;
extern CFStringRef const kCTRegistrationCellId;
CFStringRef CTSIMSupportCopyMobileSubscriberCountryCode(CFAllocatorRef);
CFStringRef CTSIMSupportCopyMobileSubscriberNetworkCode(CFAllocatorRef);
id CTTelephonyCenterGetDefault();
void CTTelephonyCenterAddObserver(id, void, CFNotificationCallback, CFStringRef, void, CFNotificationSuspensionBehavior);
...
CTTelephonyCenterAddObserver(CTTelephonyCenterGetDefault(), NULL, callback, NULL, NULL, CFNotificationSuspensionBehaviorHold);
void callback(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo)
{
NSString* notification = (NSString*)name;
NSDictionary *cellInfo = (NSDictionary*)userInfo;
if ([notification isEqualToString:(NSString*)kCTRegistrationCellChangedNotification])
{
int LAC, CID, MCC, MNC;
if (cellInfo[(NSString*)kCTRegistrationGsmLac])
{
LAC = [cellInfo[(NSString*)kCTRegistrationGsmLac] intValue];
}
else if (data[(NSString*)kCTRegistrationLac])
{
LAC = [cellInfo[(NSString*)kCTRegistrationLac] intValue];
}
if (cellInfo[(NSString*)kCTRegistrationGsmCellId])
{
CID = [cellInfo[(NSString*)kCTRegistrationGsmCellId] intValue];
}
else if (cellInfo[(NSString*)kCTRegistrationCellId])
{
CID = [cellInfo[(NSString*)kCTRegistrationCellId] intValue];
}
MCC = [[(NSString*)CTSIMSupportCopyMobileSubscriberCountryCode(NULL) autorelease] intValue];
MNC = [[(NSString*)CTSIMSupportCopyMobileSubscriberNetworkCode(NULL) autorelease] intValue];
}
}
3) This returns current serving cell tower
struct CTResult
{
int flag;
int a;
};
id _CTServerConnectionCreate(CFAllocatorRef, void*, int*);
#ifdef __LP64__
void _CTServerConnectionGetLocationAreaCode(id, int*);
void _CTServerConnectionGetCellID(id, int*);
#else
void _CTServerConnectionGetLocationAreaCode(struct CTResult*, id, int*);
#define _CTServerConnectionGetLocationAreaCode(connection, LAC) { struct CTResult res; _CTServerConnectionGetLocationAreaCode(&res, connection, LAC); }
void _CTServerConnectionGetCellID(struct CTResult*, id, int*);
#define _CTServerConnectionGetCellID(connection, CID) { struct CTResult res; _CTServerConnectionGetCellID(&res, connection, CID); }
#endif
...
int CID, LAC, MCC, MNC;
id CTConnection = _CTServerConnectionCreate(NULL, NULL, NULL);
_CTServerConnectionGetCellID(CTConnection, &CID);
_CTServerConnectionGetLocationAreaCode(CTConnection, &LAC);
MCC = [[(NSString*)CTSIMSupportCopyMobileSubscriberCountryCode(NULL) autorelease] intValue];
MNC = [[(NSString*)CTSIMSupportCopyMobileSubscriberNetworkCode(NULL) autorelease] intValue];
UPDATE
On ARM64 (iPhone 5S) there is an issue with all CoreTelephony functions that accept struct CTResult argument. Apparently, 64-bit version of CoreTelephony exports these functions without struct CTResult argument. Because of that you will get an error on ARM64 if you call these functions like you did in the past - arguments will be wrong. I updated function declarations so that they work on both 32-bit and 64-bit ARM architectures. I tested it and it works on both iPhone 4S and iPhone 5S.
This only applies to ARM64. If you build your project for 32-bit ARM architecture then there is no such issue. Your application will use 32-bit version of CoreTelephony which expects struct CTResult argument.
8.3 UPDATE
As of iOS 8.3 all of the above solutions require entitlement to work
<key>com.apple.CommCenter.fine-grained</key>
<array>
<string>spi</string>
</array>
Not only cell monitor is protected but it seems like all of the CoreTelephony notifications now require that entitlement to work. For example, kCTMessageReceivedNotification also affected.
suscriberCellularProvider is an object method (vs class method).
You can take a look how to use it here:
Determine iPhone user's country
I think CTCarrier has MCC and MNC.
You can check network type using the code from this question:
How to check if iPhone supports CDMA or GSM
And look this question for CellID:
CTServerConnectionGetCellID routine core telephony
The code below is how to insert to che entitlement to meke the code work on ios 8.3.
As of iOS 8.3 all of the above solutions require entitlement to work
<key>com.apple.CommCenter.fine-grained</key>
<array>
<string>spi</string>
</array>
Indeed, tha above code mentioned is said that can be run to get the lac and cell on ios 8.3 and above. But I really don't know how to insert the above on a jailbroken phone. Could anyone give any detail information.
We know that we call pthread like this
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void* arg);
However, if in the start_routine function I wanna call has more than one argument, what can I do?
You can put whatever you want into a struct and pass a pointer to that.
In C:
typedef struct {
int a;
int b;
} ChildMainArgs;
void child_main(int a,int b);
void child_main_thread(void *arg)
{
ChildMainArgs *args_ptr = (ChildMainArgs *)arg;
child_main(args_ptr->a,args_ptr->b);
}
ChildMainArgs args;
args.a = 5;
args.b = 7;
pthread_create(..,..,child_main_thread,&args);
I want to add reference to DNSSDObjects to a project in MonoTouch, specifically DNSServiceResolve object.
I want to access DNSServiceResolve in a MonoTouch project but cant find that class anywhere.
How can that be done ?
I got the functions from dns_sd.h working with P/Invokes. Most of the definitions were already done in the project zeroconfignetservices [1], specifically in the file mDNSImports.cs. Instead of referencing dnssd.dll, it is /usr/lib/system/libsystem_dnssd.dylib on iOS.
So for example, the definition for DNSServiceQueryRecord would be:
[DllImport("/usr/lib/system/libsystem_dnssd.dylib")]
public static extern DNSServiceErrorType DNSServiceQueryRecord(out IntPtr sdRef,
DNSServiceFlags flags,
UInt32 interfaceIndex,
[MarshalAs(
UnmanagedType.CustomMarshaler,
MarshalTypeRef = typeof(Utf8Marshaler))] String fullname,
DNSServiceType rrType,
DNSServiceClass rrClass,
DNSServiceQueryReply callBack,
IntPtr context);
And a query for an SRV record would be as follows:
public void DoDnsLookup()
{
IntPtr sdRef;
var result = DNSServiceQueryRecord(
out sdRef,
DNSServiceFlags.LongLivedQuery,
0,
"_xmpp-client._tcp.gmail.com",
DNSServiceType.SRV,
DNSServiceClass.IN,
DnsServiceQueryReply,
IntPtr.Zero
);
if (result == DNSServiceErrorType.NoError)
{
DNSServiceProcessResult(sdRef);
DNSServiceRefDeallocate(sdRef);
}
}
//see [2] why this method is static and the attribute
[MonoPInvokeCallback(typeof(DNSServiceQueryReply))]
public static void DnsServiceQueryReply(
IntPtr sdRef,
DNSServiceFlags flags,
UInt32 interfaceIndex,
DNSServiceErrorType errorCode,
[MarshalAs(
UnmanagedType.CustomMarshaler,
MarshalTypeRef = typeof(Utf8Marshaler))] String fullname,
DNSServiceType rrType,
DNSServiceClass rrClass,
UInt16 rdLength,
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 7)]byte[] rData,
UInt32 ttl,
IntPtr context)
{
if (result == DNSServiceErrorType.NoError)
{
// process returned DNS data in rData
// a useful library for this could be Bdev.Net.Dns [3]
}
}
All the classes, enums, etc. not defined here are from [1].
References:
http://code.google.com/p/zeroconfignetservices
http://docs.xamarin.com/ios/guides/advanced_topics/limitations#Reverse_Callbacks
dnslookup.codeplex.com