Friday, October 06, 2006

Image.createImage throws an IOException on Sprint CDMA Phones

Carrier: Sprint
Network: CDMA
Manufacturer: Sanyo
Programming Language: J2ME


I ran into an issue trying to download jpg data to a J2ME application recently, and I figured it warranted a blog post. 

The data the comes over the air is a bunch of meta data about the image, followed by all the bytes that are the contents of the image.  When the request comes in I find where the Image starts and try to load it into an Image object.  The Image object has a method:

Image.createImage(byte[] buffer, int start, int length)

which is perfect.  I figured I could just pass in the whole response with the right start index and length, and it would work perfect.  When I tested it, it worked great on IDEN phones, and some sprint phones, but on a number of them, Sanyo phones in particular, it would only work a small fraction of the time.  Most of the time it would return a IOException with a null message. 

After debugging this for a few hours, I found that the data being sent from the server was being received right by the phone, and that the phone was using the correct start index and length.  Then I found that if the same contents were sent to two different phones, one would work and one would fail.  I couldn't figure out why it would fail, and it really didn't make any sense.

Fortunately I was able to come up with a workaround that I haven't seen on the Internet yet, hence this blog...

Instead of passing in the whole buffer, with start and length values, I just the image bytes into a new array and pass in 0 for start and the length of the array for the length.

This solved the problem, but blew my mind.  :) 

Original Code that crashed:

                     Image img = null;
                     try {
                        img = Image.createImage(output, imageStartIdx, length)
                     } catch(Exception e) {
                        throw new Exception("The map returned was not valid.");
                     }

After The Fix:

                     byte[] imageBytes = new byte[length];
                     System.arraycopy(output, imageStartIdx, imageBytes, 0, length);
                    
                     Image img = null;
                     try {
                        img = Image.createImage(imageBytes, 0, imageBytes.length);
                        // img = Image.createImage(output, imageStartIdx, length)
                     } catch(Exception e) {
                        throw new Exception("The map returned was not valid.");
                     }

This is nothing too impressive, but I figured someone might not figure it out on their own, so there it is...

Happy Coding!

Thursday, September 28, 2006

.mobi Domain Names

.mobi has been introduced as the defacto for mobile websites, and though it's pretty intuitive, (mobi->mobile), imagine typing it on your phone.  M and O are on the same key, so you would have to type:

6
wait about 5 seconds
6
6
6
2
2
4
4
4


What a pain...

The Nerd community, like me, knows that web content for phones has clasically been refered to as "WAP pages", WAP being Wireless Application Protocol,  and though I'm not a huge fan of the term, it's always been particulary convinient, because W-A-P is not only on 3 different keys on a phone, but each letter is the first letter for it's key, so instead of the above key sequence a .wap extension would be entered with the following:
9
2
7

That saves 7 key strokes, and a ton of time... I'm not going to talk to much smack, but it seems like there was not nearly enough thought on this one.  I suppose one day WAP browsers will assume that the extension is .mobi if no other extension is specified, so it won't matter anyway, but for all of us with old phones, it will always be a pain.  Such is life I suppose.

Wednesday, August 16, 2006

The Motorola i580 is NOT my phone of choice

Nextel now sells the i580. It looks nice at first... it's very rugged, and comes equiped with a 1.3 MP camera. After playing with it for a while, I came to the conclussion that the Motorola iden group is heading in the right direction, but still isn’t anywhere near where they should be.

...Major Points:

The Record Store Is Much Faster.

In older iden phones (even ones with higher model numbers) always had a very sluggish record store. Any time you had to write data to the memory store, especially when you store lots of data, it would always run super slow. CDMA phone always had iden phones beat. The i580 is much faster, and is finally competitive on Record Store performace.

The Up stream network IO is HORRIBLE!

I loaded up an app onto the i580 and the i870, and I found that the network upload speeds on the i580 were about 4 times slower, and that’s a generous estimate. The download speeds seem to be competitive (at least with other iden phones). In addition to the slow speeds, you can not usually make it through a large upload without being interrupted by a random socket error, so really we shouldn’t even worry about the fact that it’s slow, instead we should just try to get it to work period.

The i580 does have widen, iden’s high(er) speed data, support… but I haven’t tried it yet, that may help getting around this horrible performance.

There are a lot of new bells and whistles on the i580, but the network IO is enough to make me say that I would advise against buying this phone until it is resolved.

Sunday, July 02, 2006

SQL Server Index Fragmentation

SQL Server, but like most nice tools, it doesn't come without it's short comings. Among the list of short comings is Index Fragmentation. You add an index to a table to make a certain column a good candidate to look up data with. Behind the scenes, this index is really basically just a sorted table with a lot less data than the big table so that you can lookup the record in the sorted table, and then use the key to get record from the big table. This makes things nice and fast... But over time the indexes slowly get fragmented, and selecting data gets slower and slower. Most people think that it gets slow because there is just too much data, but computers are FAST! And they are good at handling lots of data... That's why we made them :) the problem is that these indexes become so fragmented that they are basically useless.

How do you fix it?
Well before you fix it you need to know what's broken. You can use the "DBCC SHOWCONTIG" command (find details on how to use this and all commands at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/tsqlref/ts_tsqlcon_6lyk.asp) this command will tell you all you need to know (and a lot that you don't need to know) about the indexes you ran it on. You can run it across the whole database, a single table, or even a single index. If you are only interested in the fragmentation, you probably want to look at the "Extent Scan Fragmentation" field that it outputs... The closer to 0, the better.

Next, if you determine you have a lot of fragmentation, you have a number of options to resolve the issue. The Naive approach is to drop the index and recreate it, and actually this will give you the best final results, but in the mean time anyone using your DB will be running without an index, and that will cause horrible performance for them. For this reason, SQL Server provides a number of other options.

My favorite is the "DBCC DBREINDEX" you just give this command an index, and it churn for a while and end up giving you a new fast index. There is also a "DBCC INDEXDEFRAG" which keeps the index, but shifts around all the info in it to try to defrag it. I don't use it, but I've heard that it has decent results, and doesn't cause as much data locking as all other solutions. The last option is recreating the index with the DROP_EXISTING clause. I'm no expert but I believe this syntax is supported by most databases, and the DBCC commands are SQL Server specific. But recreating the index, even if you use the DROP_EXISTING clause has most of the same disadvantages of dropping and recreating.

Moral of the story? You have to change the oil in your car from time to time... We don't like to do it, but we have to do it. Indexes are not much different. They require maintenance. :-p

Wednesday, June 21, 2006

RecordStream issue with LG 535 (Fusic)

Areas of interest: J2ME, Sprint/Nextel, CDMA, LG Fusic (535), RecordControl.setRecordStream

I’m working with the J2ME for the Fusic, an awesome new CDMA cell phone from LG.  I’ve noticed that the AudioRecording doesn’t seem to work right.

When I try to set the output stream of the RecordControl via the RecordControl.setRecordStream() method, it throws an IO Exception (which it’s not documented to throw).  The exception is as follows:

java.io.IOException: Could not create recording at given location

It’s almost like its trying to use the RecordLocation instead of the stream.  The RecordLocation is a locator string that specifies a URL to save the media to.

I’m only making note of it, I have no solution at this issue.  I plan to disable audio recording for now on this phone in the mean time, but since I couldn’t find any mention of this on google, I figured I’d mention it here so you know you’re not the only one seeing this problem.  If anyone does happen to solve the problem, feel free to post additional details here.  I suspect that you could work around it by using the setRecordLocation and actually recording that way, then going back and pulling it out from that location.

 

Good Luck.

Friday, June 16, 2006

View-Based Refresh Queries

Google Earth is a super cool application to dork out on... I've done a ton of work with KML, the Keyhole Markup Language. But no matter how much I do with it, it still continues to blow my mind.

Right now I'm working on a project with google to provide content via View-Based Refresh Queries. These are queries where you provide a url and they post a GET request to you and you feed back KML. Their request contains the corner lat/lon points so you just decide what you think should show up in Google Earth, then generate the KML and return it in your response. The concept is simple, but the actual work involoved is not as trivial as it sounds. When google Earth loads, they are zoomed way out, and basically you can see the whole earth... so what do you return? data for the whole earth? probably not... that would kill your database, and the client would be stuck downloading everything you had. and if you only return a subset of the data, how do you choose what to return? You want to spead it out so that the data that you show is scattered around the world, then when they zoom in, you want to show more places in the zoomed in level. And what kind of data do you show? At a high level, you want a complex collection of data to be represented as a single point probably, but as they get closer you want to show more and more data about the complex thing. All of this logic, which I've only started to dip into here is what takes the time. And with the masses that google can provide, these questions are very important.

My Manager estimated that this project could be done in a matter of days, and *something* can be done in a matter of days, but the solution should be load tested and usability tested, and really, even the server architecture should be reconsidered. I really am worried that a million people will all start hitting our servers all at once, and I don't think we're ready for that :)

So how do I make this situation work?
-first, direct all traffic to some subdomain like googleearth.yourdomain.com and have your main server host that subdomain... this way when the traffic kills you you can issolate it and move it somewhere else, or just turn it off.
-second, write it without strong consideration for the consequences. you can get it done now, then prove it needs more time by load testing it and showing that it is not scallable.
-third, work harder

The saga continues

I've been keeping a few blogs on a drupal installation on an old solaris box I had around, but I've been trying to change my nerdy habits... it's cool to be a nerd, but why waste all your time doing something that the rest of the world can do better using free stuff like this? for respect? who cares! :)

What is this blog for?

I'll keep another personal blog, this one will be reserved for nerdier things than your average person wants to hear about.

Why would I read this blog?

because your a nerd too.

What kind of stuff will it contain?

This blog will only rant about things that I either work with, or have worked with. I work for one of the leading GPS compaines in the world, working with various trechnologies... I'm always working with KML, GoogleMaps, Geodedic Math, C#, Java, XML, XSL, all the dorky stuff that people like you and me are all about.

Should I trust this Blog?

No. The internet makes you stupid. I'll do exactly what every other nerd does, pretend I am awesome and that I know everything... oddly enough I don't. You can always read, and you can choose to accept or reject whatever you want, but I am not anything special. and itf you blindly trust me, you are a sucker! :-p

What good does Blogging do?

I will not promote this... If I have anything good to say, Googles web crawler will promote it for me, and if it doesn't then I obveously didn't have anything good to say. If you're reading this, then I guess I must have said something worth reading:) weird!

I don't plan to move over my old blogs, but I'll leave them up where they were... If you find them, feel free to indulge