Programmatically send iMessage using private frameworks - ios

Does anyone know if it's possible to directly send an iMessage using a private framework?
I tried using CTMessageCenter from CoreTelephony but it'll send an SMS even though my phone can send iMessages.

I haven't tested this, but look at the code posted here. If you look at httpResponseForMethod:URI:, you see where he/she sends a message (appears to be hardcode to support iOS 5 or iOS 4):
CKSMSService *smsService = [CKSMSService sharedSMSService];
//id ct = CTTelephonyCenterGetDefault();
CKConversationList *conversationList = nil;
NSString *value =[[UIDevice currentDevice] systemVersion];
if([value hasPrefix:#"5"])
{
//CKMadridService *madridService = [CKMadridService sharedMadridService];
//NSString *foo = [madridService _temporaryFileURLforGUID:#"A5F70DCD-F145-4D02-B308-B7EA6C248BB2"];
NSLog(#"Sending SMS");
conversationList = [CKConversationList sharedConversationList];
CKSMSEntity *ckEntity = [smsService copyEntityForAddressString:Phone];
CKConversation *conversation = [conversationList conversationForRecipients:[NSArray arrayWithObject:ckEntity] create:TRUE service:smsService];
NSString *groupID = [conversation groupID];
CKSMSMessage *ckMsg = [smsService _newSMSMessageWithText:msg forConversation:conversation];
[smsService sendMessage:ckMsg];
[ckMsg release];
} else {
//4.0
id ct = CTTelephonyCenterGetDefault();
void* address = CKSMSAddressCreateWithString(pid);
int group = [grp intValue];
if (group <= 0) {
group = CKSMSRecordCreateGroupWithMembers([NSArray arrayWithObject:address]);
}
void *msg_to_send = _CKSMSRecordCreateWithGroupAndAssociation(NULL, address, msg, group, 0);
CKSMSRecordSend(ct, msg_to_send);
}
The code uses normal SMS, but you can see the following commented out code:
//CKMadridService *madridService = [CKMadridService sharedMadridService];
The "Madrid" service is probably what can send iMessages. See the private header here.
Both SMS and iMessage private APIs are in the ChatKit.framework.

Through a non jailbreak iPhone there is absolutely no access to the iMessage CoreTelephony API

Related

Having trouble receiving device-to-device payments using NFCISOTag7816 on iOS

I do the same transactions for both card payment and device payment.
When <NFCMifareTag: 0x280d12cc0> is received for card payment, after hexString operation, this incoming tag is transmitted to the service as 045c7d8a076b80, the tagId on my card. When I try to get payment by scanning the card again, the current tag is changed. But after the hexString operation, I still get the same tagId. For example; 045c7d8a076b80 again for <NFCMifareTag: 0x280da9fc0>.
But when I scan the device for device payment, the tagId I get after hexString operation for <NFCISO7816Tag: 0x2829d18c0> is 0803ffc6. Every time I read it, the current tag changes like on the card, but the tagId changes every time for the device. For example; For <NFCISO7816Tag: 0x282849c80> I get the id 082c58cc.
The codes I use;
id<NFCISO7816Tag> currentTag = [[tags firstObject] asNFCISO7816Tag];
dispatch_async(dispatch_get_main_queue(), ^{
NSString * tagId = [[currentTag identifier] hexString];
[self.delegate nfcManagerDidReadTag:tagId];
});
- (NSString *)hexString {
const unsigned char *bytes = (const unsigned char *)self.bytes;
NSMutableString *hex = [NSMutableString new];
for (NSInteger i = 0; i < self.length; i++) {
[hex appendFormat:#"%02x", bytes[i]];
}
return [hex copy];
}
Is there anything else I need to do for the ISO7816 Tag? Is it available for apple to use the tag I read from the device? What operation can I do on the tag I read to get the same required tagId every time?
Or I need your suggestions if I need to use another tag and another way. Thank you.

Can I use Unix socket for local communication between two iOS applications

Background: I have two iOS applications that need to exchange data locally with each other. The ideal scenario is that app A calls app B into foreground using URL scheme, with app A in the background, the two apps could exchange data with each other multiple rounds. I can declare app A the ability to run in background(I have valid reason to do so) so background execution for A is not a problem. I don't want to continue using URL scheme for the data exchange part between two apps because using URL scheme will open the other app and that means these two apps will be opened multiple times if there is multiple rounds of data exchange.
Also please note that these two iOS applications do not belong to the same developer so anything that relies on app group to share data will not work in this case...
Currently I have found a solution using a Unix Internet Domain Socket that binds onto the local loopback interface. It is technically working but I don't know if Apple permits this or not? Is there any better way to do this?
This is the code for the unix socket:
For the server app(app A):
BOOL _listenForConnections = false;
int listenfd = 0;
struct sockaddr_in serv_addr;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(8008);
bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
_listenForConnections = true;
listen(listenfd, 10);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(#"Waiting for connections...");
while (_listenForConnections)
{
__block int connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);
NSLog(#"Connection accepted");
char buffer[4096];
bzero(buffer, 4096);
NSString *message = #"";
bool continueReading = true;
do{
recv(connfd , buffer , 4096 , 0);
continueReading = false;
NSLog(#"%#", [NSString stringWithFormat: #"%#", [NSString stringWithFormat: #"Received message from client: %#%s", message, buffer]]);
}while (continueReading);
char* answer = "Hello World";
write(connfd, answer, strlen(answer));
NSLog(#"%#", [NSString stringWithFormat: #"Sent response to client"]);
}
NSLog(#"Now stop listening for connections");
close(listenfd);
});

open cash drawer with TM-T81 epson iOS SDK

I want to open a cash drawer which I have bought its printer driven cash drawer. And I have an Epson TM-T81 receipt printer.
I get a delegate called when I open and close the printer manually but I want to open it automatically when receipt is printed.
The code I have written is :
-(void)openDrawer{
EposBuilder *builder = [[EposBuilder alloc] initWithPrinterModel:#"TM-P20" Lang:0];
if(builder == nil){
return ;
}
//add command
int result;
result = [builder addPulse:EPOS_OC_DRAWER_1 Time:EPOS_OC_PULSE_100];
NSLog(#"%d command result",result);
NSString *str = #"27 112 48 55 121";
NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
result = [builder addCommand:data];
NSLog(#"%d pulse",result);
if(result != EPOS_OC_SUCCESS){
NSLog(#"cut failed");
return ;
}
//send builder data
unsigned long status = 0;
unsigned long battery = 0;
result = [printer sendData:builder Timeout:10000 Status:&status Battery:&battery];
//remove builder
[builder clearCommandBuffer];
}
Looking for a solution from experts like you.
Checkout the documentation.
http://spsrprofessionals.com/ClientSite/readers/ePOS-Print_SDK_141020E/iOS/ePOS-Print_SDK_iOS_en_revN.pdf#page98
You're looking for the addPulse method of the builder.
The only need you need to know is what jack the cash drawer is connected to if you printer has more than one cash drawer jack.
I added below the line of code and got working for the TM-T20 series.
[printer_ addPulse:EPOS2_DRAWER_HIGH time:EPOS2_PULSE_100];

detect hotspot enabling in iOS with private api's

ok so i want to detect weather the user has enabled hotspot/tethering or not in a iOS device. I can use private api's knowing it wont make it to the app store.
i was trying to go through private api's list/ runtime headers but there are too many to decide which might be helpful.
or if i could get to know where UIApplicationWillChangeStatusBarFrameNotification gets fired from in private api's(probably called for active call and activated hotspot etc)
i tried this detect personal hotspot and also used CaptiveNetwork but it only returns the connected wi-fi ssid and not the created hotspot.
any knowledge shared will be extremely helpful
Update: #creker
With the above code the compiler shows the error " SCDynamicStoreCreate is unavailable: not available on iOS. So i went into SCDynamicStore.h and changed the following
SCDynamicStoreRef
SCDynamicStoreCreate (
CFAllocatorRef allocator,
CFStringRef name,
SCDynamicStoreCallBack callout,
SCDynamicStoreContext *context
) __OSX_AVAILABLE_STARTING(__MAC_10_1,__IPHONE_NA);
to
SCDynamicStoreRef
SCDynamicStoreCreate (
CFAllocatorRef allocator,
CFStringRef name,
SCDynamicStoreCallBack callout,
SCDynamicStoreContext *context
) __OSX_AVAILABLE_STARTING(__MAC_10_1,__IPHONE_6_0);
now i am able to get the dictionary with the states 1022 and 1023. Just wanted to confirm by changing the file like this(not done before) will i have any problem in archiving build(or any other problem) other then the fact that we know this code won't make it to the app store
Without Private APIs
You can detect active personal hotspot by enumerating network interfaces using C APIs. When hotpost is active and someone is connected to it there will be interface with bridge prefix. On my iPhone 5 it's bridge100. If hotspot is disabled or no one is connected to it that interfaces will not even be in the list.
C APIs will even return you IP address and subnet mask in that network.
That's what I'm using in my applications to detect active hotspot.
To get SSID you need [[UIDevice currentDevice] name] - personal hotspot SSID always matches device name.
With Private APIs
You can obtain all the information about personal hotspot using this code:
SCDynamicStoreRef sc = SCDynamicStoreCreate(NULL, CFSTR("com.apple.wirelessmodemsettings.MISManager"), NULL, NULL);
NSDictionary* info = (__bridge_transfer NSDictionary*)SCDynamicStoreCopyValue(sc, CFSTR("com.apple.MobileInternetSharing"));
CFRelease(sc);
info dictionary will look something like this when hotspot is active and has connections:
{
Errnum = 0;
ExternalInterfaces = (
"pdp_ip0"
);
Hosts = {
Current = 1;
Max = 5;
MoreAllowed = 1;
Type = {
AirPort = 0;
Bluetooth = 0;
Ethernet = 0;
"USB-Ethernet" = 1;
};
};
InternalInterfaces = (
bridge100
);
Reason = 0;
State = 1023;
Version = 2;
}
When hotspot is active but there are no connections:
{
Errnum = 0;
ExternalInterfaces = (
);
Hosts = {
Current = 0;
Max = 5;
MoreAllowed = 1;
Type = {
AirPort = 0;
Bluetooth = 0;
Ethernet = 0;
"USB-Ethernet" = 0;
};
};
InternalInterfaces = (
);
Reason = 0;
State = 1023;
Version = 2;
}
When hotspot is not active:
{
Errnum = 45;
ExternalInterfaces = (
);
Hosts = {
Current = 0;
Max = 5;
MoreAllowed = 1;
Type = {
AirPort = 0;
Bluetooth = 0;
Ethernet = 0;
"USB-Ethernet" = 0;
};
};
InternalInterfaces = (
);
Reason = 0;
State = 1022;
Version = 2;
}
State key will be equal to 1023 when hotspot is active regardless of active connections. I don't know whether that value contains bit-flags or not. iOS is actually checking if value is equal to 1023.
SCDynamicStore APIs are from public SystemConfiguration framework but marked as not available on iOS platform. That means all the headers are there, you just need to copy definitions without __OSX_AVAILABLE_STARTING macro.
You can even observe changes to that setting - you can specify a key which value you want to observe. Read Apple documentation for implementation details.
UPDATE
So i went into SCDynamicStore.h and changed the following
I wouldn't do that. It shouldn't cause any problems but for me changing SDK headers is not a good solution. I suggest the following. Don't include the framework headers. Make your own header where you copy all the methods you need with __OSX_AVAILABLE_STARTING changed or removed.

Getting Device ID or Mac Address in iOS [duplicate]

This question already has answers here:
How can I programmatically get the MAC address of an iphone
(12 answers)
Closed 9 years ago.
I have an application that uses rest to communicate to a server, i would like to obtain the iphones either mac address or device ID for uniqueness validation, how can this be done?
[[UIDevice currentDevice] uniqueIdentifier] is guaranteed to be unique to each device.
uniqueIdentifier (Deprecated in iOS 5.0. Instead, create a unique identifier specific to your app.)
The docs recommend use of CFUUIDCreate instead of [[UIDevice currentDevice] uniqueIdentifier]
So here is how you generate an unique id in your app
CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault);
NSString *uuidString = (NSString *)CFUUIDCreateString(NULL,uuidRef);
CFRelease(uuidRef);
Note that you have to save the uuidString in user defaults or in other place because you can not generate the same uuidString again.
You can use UIPasteboard to store your generated uuid. And if the app will be deleted and reinstalled you can read from UIPasteboard the old uuid. The paste board will be wiped out when the device will be erased.
In iOS 6 they have introduced the NSUUID Class that is designed to create UUIDs strings
Also they added in iOS 6 #property(nonatomic, readonly, retain) NSUUID *identifierForVendor to the UIDevice class
The value of this property is the same for apps that come from the
same vendor running on the same device. A different value is returned
for apps on the same device that come from different vendors, and for
apps on different devices regardless of vendor.
The value of this property may be nil if the app is running in the
background, before the user has unlocked the device the first time
after the device has been restarted. If the value is nil, wait and get
the value again later.
Also in iOS 6 you can use ASIdentifierManager class from AdSupport.framework. There you have
#property(nonatomic, readonly) NSUUID *advertisingIdentifier
Discussion Unlike the identifierForVendor property of the UIDevice,
the same value is returned to all vendors. This identifier may
change—for example, if the user erases the device—so you should not
cache it.
The value of this property may be nil if the app is running in the
background, before the user has unlocked the device the first time
after the device has been restarted. If the value is nil, wait and get
the value again later.
Edit:
Pay attention that the advertisingIdentifier may return
00000000-0000-0000-0000-000000000000
because there seems to be a bug in iOS. Related question: The advertisingIdentifier and identifierForVendor return "00000000-0000-0000-0000-000000000000"
For a Mac Adress you could use
#import <Foundation/Foundation.h>
#interface MacAddressHelper : NSObject
+ (NSString *)getMacAddress;
#end
implentation
#import "MacAddressHelper.h"
#import <sys/socket.h>
#import <sys/sysctl.h>
#import <net/if.h>
#import <net/if_dl.h>
#implementation MacAddressHelper
+ (NSString *)getMacAddress
{
int mgmtInfoBase[6];
char *msgBuffer = NULL;
size_t length;
unsigned char macAddress[6];
struct if_msghdr *interfaceMsgStruct;
struct sockaddr_dl *socketStruct;
NSString *errorFlag = NULL;
// Setup the management Information Base (mib)
mgmtInfoBase[0] = CTL_NET; // Request network subsystem
mgmtInfoBase[1] = AF_ROUTE; // Routing table info
mgmtInfoBase[2] = 0;
mgmtInfoBase[3] = AF_LINK; // Request link layer information
mgmtInfoBase[4] = NET_RT_IFLIST; // Request all configured interfaces
// With all configured interfaces requested, get handle index
if ((mgmtInfoBase[5] = if_nametoindex("en0")) == 0)
errorFlag = #"if_nametoindex failure";
else
{
// Get the size of the data available (store in len)
if (sysctl(mgmtInfoBase, 6, NULL, &length, NULL, 0) < 0)
errorFlag = #"sysctl mgmtInfoBase failure";
else
{
// Alloc memory based on above call
if ((msgBuffer = malloc(length)) == NULL)
errorFlag = #"buffer allocation failure";
else
{
// Get system information, store in buffer
if (sysctl(mgmtInfoBase, 6, msgBuffer, &length, NULL, 0) < 0)
errorFlag = #"sysctl msgBuffer failure";
}
}
}
// Befor going any further...
if (errorFlag != NULL)
{
NSLog(#"Error: %#", errorFlag);
return errorFlag;
}
// Map msgbuffer to interface message structure
interfaceMsgStruct = (struct if_msghdr *) msgBuffer;
// Map to link-level socket structure
socketStruct = (struct sockaddr_dl *) (interfaceMsgStruct + 1);
// Copy link layer address data in socket structure to an array
memcpy(&macAddress, socketStruct->sdl_data + socketStruct->sdl_nlen, 6);
// Read from char array into a string object, into traditional Mac address format
NSString *macAddressString = [NSString stringWithFormat:#"%02X:%02X:%02X:%02X:%02X:%02X",
macAddress[0], macAddress[1], macAddress[2],
macAddress[3], macAddress[4], macAddress[5]];
//NSLog(#"Mac Address: %#", macAddressString);
// Release the buffer memory
free(msgBuffer);
return macAddressString;
}
#end
Use:
NSLog(#"MAC address: %#",[MacAddressHelper getMacAddress]);
Use this:
NSUUID *id = [[UIDevice currentDevice] identifierForVendor];
NSLog(#"ID: %#", id);
In IOS 5 [[UIDevice currentDevice] uniqueIdentifier] is deprecated.
It's better to use -identifierForVendor or -identifierForAdvertising.
A lot of useful information can be found here:
iOS6 UDID - What advantages does identifierForVendor have over identifierForAdvertising?
Here, We can find mac address for IOS device using Asp.net C# Code...
.aspx.cs
-
var UserDeviceInfo = HttpContext.Current.Request.UserAgent.ToLower(); // User's Iphone/Ipad Info.
var UserMacAdd = HttpContext.Current.Request.UserHostAddress; // User's Iphone/Ipad Mac Address
GetMacAddressfromIP macadd = new GetMacAddressfromIP();
if (UserDeviceInfo.Contains("iphone;"))
{
// iPhone
Label1.Text = UserDeviceInfo;
Label2.Text = UserMacAdd;
string Getmac = macadd.GetMacAddress(UserMacAdd);
Label3.Text = Getmac;
}
else if (UserDeviceInfo.Contains("ipad;"))
{
// iPad
Label1.Text = UserDeviceInfo;
Label2.Text = UserMacAdd;
string Getmac = macadd.GetMacAddress(UserMacAdd);
Label3.Text = Getmac;
}
else
{
Label1.Text = UserDeviceInfo;
Label2.Text = UserMacAdd;
string Getmac = macadd.GetMacAddress(UserMacAdd);
Label3.Text = Getmac;
}
.class File
public string GetMacAddress(string ipAddress)
{
string macAddress = string.Empty;
if (!IsHostAccessible(ipAddress)) return null;
try
{
ProcessStartInfo processStartInfo = new ProcessStartInfo();
Process process = new Process();
processStartInfo.FileName = "arp";
processStartInfo.RedirectStandardInput = false;
processStartInfo.RedirectStandardOutput = true;
processStartInfo.Arguments = "-a " + ipAddress;
processStartInfo.UseShellExecute = false;
process = Process.Start(processStartInfo);
int Counter = -1;
while (Counter <= -1)
{
Counter = macAddress.Trim().ToLower().IndexOf("mac address", 0);
if (Counter > -1)
{
break;
}
macAddress = process.StandardOutput.ReadLine();
if (macAddress != "")
{
string[] mac = macAddress.Split(' ');
if (Array.IndexOf(mac, ipAddress) > -1)
{
if (mac[11] != "")
{
macAddress = mac[11].ToString();
break;
}
}
}
}
process.WaitForExit();
macAddress = macAddress.Trim();
}
catch (Exception e)
{
Console.WriteLine("Failed because:" + e.ToString());
}
return macAddress;
}

Resources