Wednesday, February 22, 2012

HTC Trophy 7 Compass Magnetic Declination gives incorrect True North

My HTC Trophy 7 and Nokia Lumia 800 seem to be having an issue determining true north from magnetic north.

HTC Trophy 7 Compass Magnetic Declination

The magnetic north detection is correct (the light yellow line that matches the actual compass) but the magnetic declination is out by about 90°. The resulting true north is shown as the orange line. It should be about 22° to the west of magnetic north for my location.

You can use Raw Compass Data from the Marketplace to check the compass on your own phone.

More recently I've seen exactly the same issue on the Nokia Lumia 710 and 800 as well as an LG Quantum. (update June 25 2012 - also reported on HTC Titan)

Nokia Lumia 800 Compass Magnetic Declination

I've raised this with:


Question to HTC

The compass on my phone is out by 180 degrees. I.e. North is actually pointing South.
It is the same in several applications so it appears to be an issue with the phone rather than the app in question.
How can I resolve this?

There was then a bit of correspondence to determine the IMEI for my phone and OS version (7.10.7740.16) at the time.

Feedback from HTC

Thanks for replying to HTC.

Please visit the link below regarding the Windows Mango update:

The link states that some service and features might not be available or might behave differently after the update. Usually, there are some unexpected bugs that occur whenever there is new software written. Though the Windows Mango is just an update to the Windows 7 platform, it contains a big number of new features. If there is an unexpected bug, it would take time to test, isolate and come up with an update to fix the said issue.

For the meantime, we suggest that you perform a factory reset. This usually fixes the issues that arise from updating the software. Hard reset is same as restoring your HTC phone to its default settings - the way it was when you first purchased it and turned it on.

Please be advised that doing a factory reset will delete all your data (such as contacts, calendar notes, SMS and installed applications) in your phone memory. You will not be able to recover the information once they are deleted.

We have attached the user guide in performing factory reset for your reference.

Should you need further assistance, please feel free to share your preferred contact schedule with us as we would be more than happy to contact you directly over the phone.

My response

I've done some further investigation on this after developer unlocking my phone.
It would appear that the magnetic compass heading returned by the Magnetometer is correct but the resulting true North heading is significantly out.

I checked and got the following details back for my location:
Latitude: 41° 16' 25.2" S
Longitude: 173° 16' 54.7" E
Magnetic declination: 21° 58' EAST
Declination is POSITIVE
Inclination: -66° 44'
Magnetic field strength: 56442.2 nT

The phone is giving a magnetic declination of approximately 130° which seems wrong given my current latitude and longitude.

How does the phone determine the magnetic declination? Is it part of the WP7 operating system or part of the phone? Do I need to enable location services to get the correct value?

HTCs next response

We appreciate the prompt reply.

We recommend getting in touch with your retailer to have the phone assessed. We are only relying on the updates that Microsoft is sending. The distributors of the phone customizes them.

Have a nice day!

Friday, February 17, 2012

Disabling a Salesforce trigger when setting up test case data

When setting up test case data from an Apex test method I needed a technique to disable triggers that were firing and causing a LimitException: "Too many SOQL queries: 101". The triggers weren't the target of the test case and in some scenarios could cause the test method to fail before the target method and assertions could be called.

I didn't want to disable the triggers for every test case. Just in certain cases as the required data was being set up.

Option 1

Wrap the setup phase code of the test method with System.runAs().

In the trigger do nothing if Test.isRunningTest() and UserInfo.getName() equals the specified user that the testMethod specifies in the runAs().

If you are creating the User as part of the test case ensure the Username is sufficiently unique. I've had the DUPLICATE_USERNAME exception in production and not the sandbox as the username has to be unique across all Salesforce instances.

Option 2

Alternatively, create a class with a static boolean variable that can be used to toggle the trigger functionality on and off.

See Also:

Thursday, February 16, 2012

Upgrading the API version of an Apex class in Salesforce

Salesforce tracks the API version used when an Apex class was created to "prevent breakages with backwards-incompatible changes".

I recently wanted to upgrade from the version 20.0 API to 24.0 API so that test methods wouldn't run with live data.

The change can be made under the Version Settings tab for the Apex Class.

Wednesday, February 15, 2012

Forcing a WP7 App to update from the marketplace

The marketplace can take a few days to prompt that an update for an App is available. If you know you don't have the latest version you can follow these steps to get it:

  1. Go to the Marketplace on the phone.
  2. Search for the app that needs the update.
  3. Open up the apps marketplace listing to view the details. You should be able to see that the current version is greater than the version you have installed.
  4. Press the Back button on your phone once to take you back to the search results.
  5. Select the app icon again and you should see that the update is available and ready to install

It occurred to me that it might be useful to provide a direct link from an applications about page to the marketplace listing using MarketplaceDetailTask.

Friday, February 10, 2012

Salesforce LimitException: Apex heap size too large

Monitoring the Heap Size

From the log files you can monitor heap memory allocation:

09:43:02:056 HEAP_ALLOCATE [62]|Bytes:5

Or get the Maximum heap size from the LIMIT_USAGE_FOR_NS log entry.

LIMIT_USAGE_FOR_NS from a sandbox:

  Number of SOQL queries: 5 out of 100
  Number of query rows: 9 out of 50000
  Number of SOSL queries: 0 out of 20
  Number of DML statements: 1 out of 150
  Number of DML rows: 1 out of 10000
  Number of script statements: 212 out of 200000
  Maximum heap size: 0 out of 6000000
  Number of callouts: 3 out of 10
  Number of Email Invocations: 0 out of 10
  Number of fields describes: 0 out of 100
  Number of record type describes: 0 out of 100
  Number of child relationships describes: 0 out of 100
  Number of picklist describes: 0 out of 100
  Number of future calls: 0 out of 10

LIMIT_USAGE_FOR_NS from production:

  Number of SOQL queries: 22 out of 100
  Number of query rows: 68 out of 50000
  Number of SOSL queries: 0 out of 20
  Number of DML statements: 0 out of 150
  Number of DML rows: 0 out of 10000
  Number of script statements: 543 out of 200000
  Maximum heap size: 5744310 out of 6000000 ******* CLOSE TO LIMIT
  Number of callouts: 3 out of 10
  Number of Email Invocations: 0 out of 10
  Number of fields describes: 0 out of 100
  Number of record type describes: 0 out of 100
  Number of child relationships describes: 0 out of 100
  Number of picklist describes: 0 out of 100
  Number of future calls: 0 out of 10

Note how the the sandbox doesn't seem to be tracking the heap size.

Use Limits to check the values in Apex:

System.debug(LoggingLevel.Debug, 'Heap Size: ' + Limits.getHeapSize() + '/' + Limits.getLimitHeapSize());
09:43:04:672 USER_DEBUG [155]|DEBUG| Heap Size: 8877586/6000000

Note how the actual Heap Size reported here is greater than the Heap Limit size! This seems to be an oddity of the sandbox environment as in production a LimitException would occur.

Use SOQL For Loops rather than standard SQOL queries

From the documentation on SOQL For Loops:

Developers should always use a SOQL for loop to process query results that return many records, to avoid the limit on heap size.

So rather than

List accs = [SELECT Id, Name FROM Account];  
for(Account a : accs){

You would have:

for(Account a : [SELECT Id, Name FROM Account]){

Use a Batch Apex or a future method

I recently had a task to upload the binary/Blob for every attachment on an opportunity to a web service as a base64 encoded string. Even after switching to a SOQL for loop it was possible to reach the standard heap size of 6000000 bytes. The attachments could be up to 5 MB in size, so just by loading the attachment Blob out of the database for one record there wasn't much space left over to base64 encode it using EncodingUtil.base64Encode.

Switching to Batch Apex increased the heap limit to 12000000 bytes. Also, by setting the scope to 1 only one attachment was processed at a time.

Tuesday, February 7, 2012

Nokia Online Marketing Tool for generating WP7 Banner Ads

Nokia have released a Online Marketing Tool (OMT) for generating banner ads directly from a WP7 Marketplace listing.
It will generate a range of dimensions and includes an option where they host the images for you.