Getting iPhone's battery level - iphone

I have a simple question. How do I get iPhone's battery level?
[UIDevice currentDevice] batteryLevel]
Simple enough? However there is a little catch - I can't use UIKit. Here is what I wrote so far, but I don't think it works:
// notification port
IONotificationPortRef nport = IONotificationPortCreate(kIOMasterPortDefault);
CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(nport), kCFRunLoopDefaultMode);
CFMutableDictionaryRef matching = IOServiceMatching("IOPMPowerSource");
kern_return_t kr = IOServiceAddMatchingNotification(nport, kIOFirstMatchNotification, matching, (IOServiceMatchingCallback)power, self, &powerIterator);
NSLog(#"Kernel said %d",kr);
power((void*)nport,powerIterator);
I'm still pretty sure you have to rely on IOKit in order to retrieve battery level. My application does not use UIKit as it is a low-level application in which UIKit cannot be used. Here are the frameworks I am using :
alt text http://img837.imageshack.us/img837/1829/screenshot20100718at211.png

A while ago I wrote a program called iox that is similar to ioreg, except it makes it easier for me to translate back to IOKit calls. When I run that on my laptop, I see the following with a battery level.
AppleSmartBattery - IOService:/AppleACPIPlatformExpert/SMB0/AppleECSMBusController/AppleSmartBatteryManager/AppleSmartBattery
CurrentCapacity = 11678
FullyCharged = YES
DesignCapacity = 13000
MaxCapacity = 11910
...
In code, that is
IOServiceNameMatching( "AppleSmartBattery" );
I have no idea if the name would be the same on iOS, but I would try either finding a program like ioreg that you can run on the iPhone, or writing something simple to log the equivalent.
ioreg is part of IOKitTools and it should just compile on iPhone.
Edit:
CFMutableDictionaryRef matching , properties = NULL;
io_registry_entry_t entry = 0;
matching = IOServiceMatching( "IOPMPowerSource" );
//matching = IOServiceNameMatching( "AppleSmartBattery" );
entry = IOServiceGetMatchingService( kIOMasterPortDefault , matching );
IORegistryEntryCreateCFProperties( entry , &properties , NULL , 0 );
NSLog( #"%#" , properties );
CFRelease( properties );
IOObjectRelease( entry );
Add some safety checks. Once you figure out the specific properties you want, you can get them directly instead of using IORegistryEntryCreateCFProperties to get them all at once.
IOKit represents everything as a big tree. IOPMPowerSource may not directly have the attributes you want, in which case you would need to iterate through the children. Using something like ioreg can tell you what you are looking for before you start coding.

I don't have any experience with jailbroken development, but this guide might be helpful.

I'm going to go for the big one: Why?
AS you probably know, you can't really not use UIKit on the iPhone, so I'm not quite sure what you're on about.

Related

Accurately reading of iPhone signal strength

There are a few questions on this already, but nothing in them seems to provide accurate results. I need to determine simply if the phone is connected to a cell network at a given moment.
http://developer.apple.com/library/ios/#documentation/NetworkingInternet/Reference/CTCarrier/Reference/Reference.html
This class seems to be documented incorrectly, returning values for mobileCountryCode, isoCountryCode and mobileNetworkCode where no SIM is installed to the phone. carrierName indicates a 'home' network or a previous home network if the phone has been unlocked.
I also looked up and found some people claiming the following to work, which uses an undocumented method of the CoreTelephony framework, but the results have been useless to me, reporting seemingly random figures, where perhaps it is not itself updating consistently.
-(int) getSignalStrength
{
void *libHandle = dlopen("/System/Library/Frameworks/CoreTelephony.framework/CoreTelephony", RTLD_LAZY);
int (*CTGetSignalStrength)();
CTGetSignalStrength = dlsym(libHandle, "CTGetSignalStrength");
if( CTGetSignalStrength == NULL) NSLog(#"Could not find CTGetSignalStrength");
int result CTGetSignalStrength();
dlclose(libHandle);
return result;
}
Thanks.
Edit: The app is connected to an internal wifi and must remain so, making a reachability check more difficult.
I'm playing with this function and I've noticed you're calling it in an interesting way. I'm calling it by adding CoreTelephony.framework as a compile-time link. For the function itself, you'll want to declare it's prototype somewhere (perhaps immediately above the method you call from):
int CTGetSignalStrength();
This needs to be declared since it isn't in a public header for CoreTelephony.
Now, I built a simple app that prints signal strength every second.
int CTGetSignalStrength();
- (void)viewDidLoad
{
[super viewDidLoad];
while (true) {
printf("signal strength: %d\n", CTGetSignalStrength());
sleep(1);
}
}
I ran it on my iPad mini and it shows steady values until I picked it up, where the number went up. Wrapping my iPad in tin foil (tin foil is a debugging tool I have never used before) caused the number to go down. When I put my iPad in airplane mode, it kept repeating the last value, so this will not be an accurate measure for you.
If you want to test if a device currently has a cellular data network connection, you may be more interested in Reachability, specifically kSCNetworkReachabilityFlagsIsWWAN.
Ok I think I have the correct solution now, which was a bit simpler in the end.
The issue with the CTGetSignalStrength() method is that it works normally, but if you remove a sim, it reports the last signal before the removal. I found another method in the same framework called CTSIMSupportGetSIMStatus(), also undocumented, which can tell you if a SIM is currently connected. Using both as follows should confirm the current network signal.
First declare the methods:
NSString * CTSIMSupportGetSIMStatus();
int CTGetSignalStrength();
Then check connectivity to cell network like so:
NSString *status = CTSIMSupportGetSIMStatus();
int signalstrength = CTGetSignalStrength();
BOOL connected = ( [status isEqualToString: #"kCTSIMSupportSIMStatusReady"] && signalstrength > 0 );

How to use kAudioUnitSubType_LowShelfFilter of kAudioUnitType_Effect which controls bass in core Audio?

i'm back with one more question related to BASS. I already had posted this question How Can we control bass of music in iPhone, but not get as much attention of your people as it should get. But now I have done some more search and had read the Core AUDIO. I got one sample code which i want to share with you people here is the link to download it iPhoneMixerEqGraphTest. Have a look on it in this code what i had seen is the developer had use preset Equalizer given by iPod in Apple. Lets see some code snippet too:----
// iPodEQ unit
CAComponentDescription eq_desc(kAudioUnitType_Effect, kAudioUnitSubType_AUiPodEQ, kAudioUnitManufacturer_Apple);
What kAudioUnitSubType_AUiPodEQ does is it get preset values from iPod's equalizer and return us in Xcode in an array which we can use in PickerView/TableView and can set any category like bass, rock, Dance etc. It is helpless for me as it only returns names of equalizer types like bass, rock, Dance etc. as i want to implement bass only and want to implement it on UISLider.
To implement Bass on slider i need values so that i can set minimum and maximum value so that on moving slider bass can be changed.
After getting all this i start reading Core Audio's Audio Unit framework's classes and got this
after that i start searching for bass control and got this
So now i need to implement this kAudioUnitSubType_LowShelfFilter. But now i don't know how to implement this enum in my code so that i can control the bass as written documentation. Even Apple had not write that how can we use it. kAudioUnitSubType_AUiPodEQ this category was returning us an array but kAudioUnitSubType_LowShelfFilter category is not returning any array. While using kAudioUnitSubType_AUiPodEQ this category we can use types of equalizer from an array but how can we use this category kAudioUnitSubType_LowShelfFilter. Can anybody help me regarding this in any manner? It would be highly appreciable.
Thanks.
Update
Although it's declared in the iOS headers, the Low Shelf AU is not actually available on iOS.
The parameters of the Low Shelf are different from the iPod EQ.
Parameters are declared and documented in `AudioUnit/AudioUnitParameters.h':
// Parameters for the AULowShelfFilter unit
enum {
// Global, Hz, 10->200, 80
kAULowShelfParam_CutoffFrequency = 0,
// Global, dB, -40->40, 0
kAULowShelfParam_Gain = 1
};
So after your low shelf AU is created, configure its parameters using AudioUnitSetParameter.
Some initial parameter values you can try would be 120 Hz (kAULowShelfParam_CutoffFrequency) and +6 dB (kAULowShelfParam_Gain) -- assuming your system reproduces bass well, your low frequency content should be twice as loud.
Can u tell me how can i use this kAULowShelfParam_CutoffFrequency to change the frequency.
If everything is configured right, this should be all that is needed:
assert(lowShelfAU);
const float frequencyInHz = 120.0f;
OSStatus result = AudioUnitSetParameter(lowShelfAU,
kAULowShelfParam_CutoffFrequency,
kAudioUnitScope_Global,
0,
frequencyInHz,
0);
if (noErr != result) {
assert(0 && "error!");
return ...;
}

openUDID using deprecated UDID

I'm looking at using openUDID inside my app for registration purposes.
However its still using the UDID number apple issues and so I was just reading though the .m file and came across this:
// One day, this may no longer be allowed in iOS. When that is, just comment this line out.
//
#if TARGET_OS_IPHONE
if([UIDevice instancesRespondToSelector:#selector(uniqueIdentifier)]){
_openUDID = [[UIDevice currentDevice] uniqueIdentifier];
}
#endif
// Take this opportunity to give the simulator a proper UDID (i.e. nullify UDID and create an OpenUDID)
//
#if TARGET_IPHONE_SIMULATOR
_openUDID = nil;
#endif
// Next we try to use an alternative method which uses the host name, process ID, and a time stamp
// We then hash it with md5 to get 32 bytes, and then add 4 extra random bytes
// Collision is possible of course, but unlikely and suitable for most industry needs (e.g.. aggregate tracking)
//
However I'm not sure exactly what line to comment out so that it used the alternative method which uses the host name, process ID, and a time stamp
You would comment out the 3 lines of code in the TARGET_OS_IPHONE block
You can "comment" out the line with uniqueIdentifier in it by prefixing that line using double slash comment.... or you can change the #if TARGET_OS_IPHONE line to #if 0, which means that block of code will never get called at all.
And then the alternative code will get used instead.
The way the code is currently written, it seems pretty safe to me to just leave it as is. Once Apple does completely do away with the uniqueIdentifier method, the instancesRespondToSelector call will properly fail and the alternative code will get used automatically.

Proper Management Of A Singleton Data Store In IOS With Web Service

I'm currently using a singleton as a data store for my app. I essentially store a number of events that are pulled and parsed from a web service and then added as needed. Each time I make a request from the web service, I parse the results and see if the items already exist. If they do, I delete them and add the updated version provided by the web service.
Everything appeared to be working properly until I fired up the Instruments panel to find out that my system is leaking the objects every time it loads them from the web service (from the second time on). The core method where things appear to be messing up is this one, which is located in my HollerStore singleton class:
- (void)addHoller: (Holler *)h
{
//Take a holler, check to see if one like it already exists
int i = 0;
NSArray *theHollers = [NSArray arrayWithArray:allHollers];
for( Holler *th in theHollers )
{
if( [[th hollerId]isEqualToString:[h hollerId]] )
{
NSLog(#"Removing holler at index %i", i);
[allHollers removeObjectAtIndex:i];
}
i++;
}
[allHollers addObject:h];
}
Quick explanation: I decided to copy the allHollers NSMutableArray into theHollers because it's being updated asynchronously by NSURLConnection. If I update it directly, it results in a crash. As such, I switched to this model hoping to solve the problem, however the Instruments panel is telling me that my objects are leaking. All the counts are exactly the # of items I have in my data set.
From what I can tell removeObjectAtIndex isn't effectively removing the items. Would love to get the thoughts of anybody else out there on three things:
Is my analysis correct that something else must be retaining the individual hollers being added?
Should I be using CoreData or SQLite for storing information pulled from the web service?
Do you know how long data stored in a Singleton should be available for? Until the app is killed?
Update
I think I've found the source, however perhaps someone can provide some clarity on the proper way to do this. I've created a method called parseHoller which takes a dictionary object created through SBJSON and returns my own model (Holler). Here are the last couple lines:
Holler *h = [[[Holler alloc] initFromApiResponse:hollerId
creatorId:creatorId
creatorName:creatorName
creatorImageUrl:creatorImage
comments:comments
attendees:attendees
wishes:wishes
invitees:invites
createdAt:createdAt
text:text
title:title
when:when]autorelease];
//(some other autorelease stuff is here to clean up the internal method)
return h;
I figured that since I'm returning an autoreleased object, this should be fine. Do you see anything wrong with this?
Have you tried to do a retain count on the objects that is leaking? Maybe that could clear up when or where it is being retained.
The code should be
[putObjectHere retainCount];
and then write to an NSLog
Hope it gives you something
Peter

How to simulate a user driving a route in a MKMapView?

I need to simulate how my application will look when a user is driving around for a demo. I have a MKMapView, how can I simulate the look of a user driving around which will use the map.userLocation functionality, which obviously will not be available in the demo.
Thanks!
No way to simulate in iPhone simulator. You'll need to load it onto your device and move around.
Well I got something going, I just did essentially this
- (void)moveIcon:(MKAnnotationView*)locationView toLocation:(CLLocation*)newLoc
{
LocationAnnotation* annotation = [[[LocationAnnotation alloc] initWithCoordinate:newLoc.coordinate] autorelease];
[locationView setAnnotation:annotation];
[map setCenterCoordinate:newLoc.coordinate animated:YES];
}
Then I call this guy in a loop between all of my vertices with a slight delay. Works quite qell.
I'm not an iPhone dev expert, but how does the map view receive the coordinates? If it's through a function that calls the CoreLocation API, could you possibly just write a function that randomly generates longitude and latitude values at a certain time interval and have your map view pull the coordinates from there instead? Just a thought.
You could also check out iSimulate which claims to be able to simulate several features only available on the iPhone in the iPhone simulator include CoreLocation. I have not tried this myself so your mileage may vary.
In order to simulate driving you'll need to establish 2 basic functionalities:
Reading CLLocations from an archive (which you'd log during the drive test with a device). Ideally you'll do this based on the timestamps on the locations, i.e. reproducing the exact same location updates which were received during the drive test.
Updating your MKAnnotationView's position on the map based on the locations read from log.
For part 1, take a look at CLLocationDispatch, a handy class which provides archiving/unarchiving of CLLocations and dispatches them to one or more listeners (using CLLocationManagerDelegate protocol).
For part 2, take a look at Moving-MKAnnotationView.
I found a better way would be to subclass MKUserLocation:
class SimulatedUserLocation: MKUserLocation {
private var simulatedCoordinate = CLLocationCoordinate2D(latitude: 39, longitude: -76)
override dynamic var coordinate: CLLocationCoordinate2D {
get {
return simulatedCoordinate
}
set {
simulatedCoordinate = newValue
}
}
}
Then add it as an annotation mapView.addAnnotation(SimulatedUserLocation()). (You might also want to hide the real location first mapView.showsUserLocation = false)
iOS would render the annotation exactly like the real user location.
dynamic is used on the property so that changing coordinate triggers KVO and moves it on the map.
The answer is NO. Then, how about adding an abstraction layer between your code and MKMapKit? You can do xUnit tests for your objective.