Browsing articles in "Tech"

Reach your customers via the brand new Broadcast center

May 18, 2013   //   by Geert Audenaert   //   News, Tech  //  No Comments

To quickly reach your customers/users/subscribers, you used to use e-mail services, which allowed you to send for example newsletters or electronic advertisements to all subscribed users. These electronic newsletters were sometimes not readable by the users, so a small percentage of your user base was not reached at all.

Instead of the hassle with electronic newsletters, you have now our Broadcast center. With the Broadcast center, you can easily broadcast messages to all users. The messages are not limited to simple news messages, you can also broadcast interactive messages, such as decision flows, coupons, polls, and so on.

More information about the Broadcast center is available in the How To.

Google App Engine development server and Python2.7

Dec 7, 2012   //   by Carl D'Halluin   //   Tech  //  No Comments

We run the Rogerthat mobile communication platform on top of Google App Engine. Some time ago we upgraded from Python2.5 to Python2.7, which gives us multi-threading and other useful features.

However, an annoying bug makes it hard to run the Google App Engine development server on Linux or Mac OS X. When starting up the server, you get lots of HTTP error 500, and your logs show errors similar to:

WARNING  2012-12-07 13:04:52,994 py_zipimport.py:139] Can't open zipfile
/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/setuptools-0.6c11-py2.7.egg:

IOError: [Errno 13] file not accessible:
'/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/setuptools-0.6c11-py2.7.egg'

This is due to a bug in the Google App Engine SDK. The fix is:

  • Edit the file <local path to app engine>/google/appengine/tools/dev_appserver_import_hook.py
    • On my system the local path to App Engine is /usr/local/google_appengine
  • Search for py27_optional=False and replace it by py27_optional=True (I had 2 matches)

Your problems should be solved. Every time you update your local App Engine SDK, you will need to redo this patch.

To run the development server with Python 2.7, we use the following script which sets up a high replication datastore, has unbuffered Python output, captures everything in a log file and streams to stdout. You should replace the path to dev_appserver.py with the one on your system:

python2.7 -u /usr/local/google_appengine/dev_appserver.py src/ --address 127.0.0.1 --port 8080 --datastore_path=tmp/datastore --history_path=tmp/datastore_history --high_replication --use_sqlite --skip_sdk_update_check 2>&1 | tee -a tmp/appengine.log

Created, designed, deployed & published a mobile service in 3 hours.

Nov 27, 2012   //   by Geert Audenaert   //   Blog, News, Tech, Testimonial  //  No Comments

This article tells the story how I created a mobile application for an existing web API using the Rogerthat platform.

Intro

A while ago, Toon Vanagt -a former colleague- introduced me to his new startup data.be. His goal is to lower the barriers for businesses to access accurate data of other businesses. See http://data.be for more information on his product. Recently they also opened up their database via a REST api (http://api.data.be). I told Toon (Toon Vanagt, co-founder of data.be) that creating a service for Rogerthat that uses his API, would be very simple. The next day he sent me an API key for his cloud based service, so I could hack something together as soon as I had some time to spend. Last sunday evening at 8pm that time had come.

Ready, Set, Go: Service homescreen

November 25, 2012 8:00:05 pm
I started with having a look at the API documentation of data.be (https://api.data.be/) to examine what functionality the service should contain.
Their api currently offers three services: validate a VAT number, check the status of a company & get some basic information (name, foundationdate, address, status, …) about a company.
Okay this meant I had to create a homescreen with three icons.

I needed about 10 minutes to identify the functionality and to add matching homescreen icons as displayed in the screenshot on the left.

References:
How to create a homescreen

Look & feel: we need a screen branding

November 25, 2012 8:10:35 pm
To give the data.be service the same look & feel as the data.be website, I had to create a screen branding. A screen branding is a reusable definition for look and feel which you can create in HTML. The HTML together with the related css files and images can be uploaded as a zip into the Rogerthat service configuration panels.
To get started, I opened the data.be website in the chrome browser. Using inspect I removed some content in the data.be website so I could take a nice screenshot of 320 pixels wide containing logo and the background they use.

The width of the screenshot (320px) is important because lots of devices have a screen width of 320 pixels or a multiple of it (iPhone 640px).

To complete the screen branding, I created the HTML in which I configured how the screen branding should behave:

<br />
&lt;html&gt;<br />
&lt;head&gt;<br />
 &lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot;/&gt;<br />
 &lt;meta property=&quot;rt:style:background-color&quot; content=&quot;#285a7d&quot;/&gt;<br />
 &lt;meta property=&quot;rt:style:show-header&quot; content=&quot;false&quot;/&gt;<br />
 &lt;meta property=&quot;rt:style:color-scheme&quot; content=&quot;dark&quot;/&gt;<br />
 &lt;style type=&quot;text/css&quot;&gt;<br />
  body { padding: 0px; margin: 0px; background-color: #285a7d;}<br />
  #background img { width: 100% }<br />
  #background { width: 100%; text-align: center; margin-bottom: 5px; }<br />
  #message { margin: 0.5em; }<br />
  #message span { font-family: Arial; font-size: 1.2em; color: white; }<br />
&lt;/style&gt;<br />
&lt;/head&gt;<br />
&lt;body&gt;<br />
&lt;div id=&quot;background&quot;&gt;&lt;img src=&quot;data.be.header.png&quot; /&gt;&lt;/div&gt;<br />
&lt;div id=&quot;message&quot;&gt;&lt;span&gt;&lt;nuntiuz_message/&gt;&lt;/span&gt;&lt;/div&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;<br />

Notice the meta tags which define how Rogerthat displays the screen branding.
Creating the screenshots, writing the HTML and packaging them together into a zip took me another 20 minutes. Off course the fact that I had done this before, and that I had a couple of other screen brandings laying around was actually an advantage.

After uploading the screen branding, I configured the home screen to use it. You can see the result on the left.

References:
How to create a Rogerthat screen branding

Finally, it is coding time!

November 25, 2012 8:30:35 pm
All right, as a developer this is the part I like the most. Now I had to add code somewhere, so that the user gets some screens after he presses the icons in his homescreen. This can be done through integrating with our api. The last few years I started using Google App Engine to create online services. So I created the integration between the APIs of Rogerthat and data.be in a Google App Engine app using Python.
First created a request handler that handles callbacks originating from the Rogerthat cloud when the user uses the data.be service in his Rogerthat app.

<br />
# Service identifier key, blanked out with stars for the example because this is a secret<br />
SIK = &quot;******&quot;<br />
# Key of the branding, also blanked out<br />
BRANDING = &quot;******&quot;</p>
<p>class DATADOTBEServiceHandler(webapp2.RequestHandler):</p>
<p>    def post(self):<br />
        self.response.headers['Content-Type'] = 'application/json'</p>
<p>        # Check whether the request can be authenticated as coming from the Rogerthat cloud<br />
        # regarding activity of the data.be Rogerthat service<br />
        sik = self.request.headers.get(&quot;X-Nuntiuz-Service-Key&quot;, None)<br />
        if sik != SIK:<br />
            logging.info(&quot;Denying request with SIK &quot; + sik)<br />
            self.response.set_status(401)<br />
            return</p>
<p>        call_json = json.loads(self.request.body)<br />
        method = call_json[&quot;method&quot;].replace(&quot;.&quot;, &quot;_&quot;)<br />
        error = None<br />
        result = None<br />
        if hasattr(self, method):<br />
            try:<br />
                result = getattr(self, method)(call_json)<br />
            except Exception, e:<br />
                logging.exception(&quot;Error occured while processing request.&quot;)<br />
                error = str(e)</p>
<p>        json.dump({'id': call_json['id'], 'result': result, 'error': error}, self.response.out)</p>
<p>    def test_test(self, call_json):<br />
        # Is called by Rogerthat to test if the callback apis are reachable and function as expected.<br />
        # See http://www.rogerthat.net/developers/getting-started/#How_to_test_your_service<br />
        return call_json[&quot;params&quot;][&quot;value&quot;]<br />

This is the basic setup I use in all my Rogerthat integration processes. It actually automates my integration with the Rogerthat callback apis so that I only need to focus on the implementing the methods that I need to implement for a specific service.
Creating an application on Google App Engine, adding this first request handler, deploying it to Google, and validating the setup from the Rogerthat service panels took me another 20 minutes.

November 25, 2012 8:51:15 pm
When the user presses the icons in the service home screen, I get a poke callback (see poke api callback documentation), so in order to react on this with a form in which the user can enter a VAT number, I need to implement this method:

<br />
class DATADOTBEServiceHandler(webapp2.RequestHandler):</p>
<p>...</p>
<p>    def messaging_poke(self, call_json):<br />
        tag = call_json[&quot;params&quot;][&quot;tag&quot;]<br />
        email = call_json[&quot;params&quot;][&quot;email&quot;]<br />
        logging.info(&quot;Received poke from %s with tag %s&quot; % (email, tag))<br />
        if tag in (&quot;is_vat_valid&quot;, &quot;company_status&quot;, &quot;company_info&quot;):<br />
            return get_vat(tag)</p>
<p>def get_vat(tag):<br />
    return dict(type='form',<br />
                value=dict(message=&quot;Voer het BTW nummer in dat u wil controleren:&quot;,<br />
                           form=dict(type=&quot;text_line&quot;, positive_button=&quot;Valideer&quot;,<br />
                                     positive_button_ui_flags=1, negative_button=&quot;Annuleren&quot;,<br />
                                     widget=dict(max_chars=15,<br />
                                                 place_holder=&quot;BTW nummer&quot;,<br />
                                                 value=None)),<br />
                           flags=64, alert_flags=1, branding=BRANDING, tag=tag))</p>
<p>

The result of this method looks like this:
This took me 30 minutes to get right.

Note: this example shows API usage which is at the time of writing not yet documented in our reference documentation but will be very soon.

 

November 25, 2012 9:21:05 pm
At this time the functionality to validate a Belgian VAT number was 50% finished. When the user presses the icon in the menu, the callback handling this request results in a screen asking the user to the enter the VAT number. The next step is to accept the input of the user, validate the VAT number and send back a screen with the results of the validation. To implement this, I added the next piece of code:

<br />
class DATADOTBEServiceHandler(webapp2.RequestHandler):</p>
<p>...</p>
<p>    def messaging_form_update(self, call_json):<br />
        logging.info(json.dumps(call_json, indent=4).encode('utf8'))<br />
        answerid = call_json[&quot;params&quot;][&quot;answer_id&quot;]<br />
        tag = call_json[&quot;params&quot;][&quot;tag&quot;]<br />
        if not answerid == &quot;positive&quot;:<br />
            # The user pressed the cancel button<br />
            return<br />
        if tag == &quot;is_vat_valid&quot;:<br />
            # The user entered the VAT number after pressing the icon to validate a VAT number<br />
            return validate_vat(call_json)</p>
<p>def validate_vat(call_json):<br />
    vat_orig = call_json[&quot;params&quot;][&quot;form_result&quot;][&quot;result&quot;][&quot;value&quot;]<br />
    if not vat_orig:<br />
        # nothing was entered, send screen to enter VAT again<br />
        return get_vat(call_json[&quot;params&quot;][&quot;tag&quot;])<br />
    # sanitize input<br />
    vat = &quot;&quot;.join((c for c in vat_orig if c in &quot;0123456789&quot;))<br />
    # callout to the data.be API to validate the VAT number<br />
    result = urlfetch.fetch(&quot;https://api.data.be/1.0/vat/%s/validity?api_id=***&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;api_key=****&quot; % vat)<br />
    # validate result of the API call<br />
    if result.status_code != 200:<br />
        logging.error(&quot;Failed to validate vat:\nstatus=%s\nerror=%s&quot; % (result.status_code, result.content))<br />
        return dict(type='message',<br />
                value=dict(message=&quot;%s is GEEN geldig BTW nummer.&quot; % vat_orig,<br />
                           answers=[], flags=1, alert_flags=1, branding=BRANDING, tag=None))<br />
    logging.info(result.content)<br />
    # parse result of API call<br />
    result = json.loads(result.content)<br />
    if not result[&quot;success&quot;]:<br />
        return dict(type='message',<br />
                value=dict(message=&quot;%s is GEEN geldig BTW nummer.&quot; % vat_orig,<br />
                           answers=[], flags=1, alert_flags=1, branding=BRANDING, tag=None))<br />
    # prepare result screen<br />
    if result[&quot;data&quot;][&quot;valid&quot;]:<br />
        message = &quot;%s is een GELDIG BTW nummer.&quot; % result[&quot;data&quot;][&quot;vat-formatted&quot;]<br />
    else:<br />
        message = &quot;%s is GEEN geldig BTW nummer.&quot; % result[&quot;data&quot;][&quot;input&quot;]<br />
    # return result screen<br />
    return dict(type='message',<br />
                value=dict(message=message, answers=[], flags=1, alert_flags=1,<br />
                           branding=BRANDING, tag=None))<br />

Adding this piece of code took me another 25 minutes.

November 25, 2012 9:45:15 pm
After 1 hour and 45 minutes I was ready with the first functionality. Luckily the two remaining features were very similar, so I could reuse quite some code to implement them as well.
The 1 hour and 15 minutes remaining, I used to add those 2 remaining features as well as adding a nice description for the data.be RogerthatĀ® service, and do some testing, before declaring it ready.

At the end I was really proud of my accomplishment, creating a mobile application on Sunday eve, which was functional, looked nice and works very good.

November 25, 2012 11:05:08 pm
Done.

To try data.be Rogerthat service I made, just search for data.be in the services tab of the Rogerthat app on your iPhone or Android app or via the Rogerthat web version accessible at https://rogerth.at

Google App Engine push task queues & the development environment

Mar 27, 2012   //   by Geert Audenaert   //   Blog, Tech  //  No Comments

Today Bart and I spent 2 hours debugging in the python Google App Engine, trying to figure out why all our scheduled tasks start to fail in the development server.

It is no secret that the public Rogerthat cloud is running on Google’s App Engine infrastructure.

To make our messaging service reliable, we make a lot of use of the deferred library which relies on the push task queue mechanism. So we kick off quite a large number of tasks.

At some point during testing on the development server, all tasks executions start to fail, flooding the logs as follows:

<br />
WARNING  2012-03-27 12:40:36,447 taskqueue_stub.py:1936] Task task4 failed to execute. This task will retry in 0.016 seconds<br />
WARNING  2012-03-27 12:40:36,455 taskqueue_stub.py:1936] Task task3 failed to execute. This task will retry in 0.032 seconds<br />
WARNING  2012-03-27 12:40:36,468 taskqueue_stub.py:1936] Task task4 failed to execute. This task will retry in 0.032 seconds<br />
WARNING  2012-03-27 12:40:36,491 taskqueue_stub.py:1936] Task task3 failed to execute. This task will retry in 0.064 seconds<br />
WARNING  2012-03-27 12:40:36,502 taskqueue_stub.py:1936] Task task4 failed to execute. This task will retry in 0.064 seconds<br />
WARNING  2012-03-27 12:40:36,558 taskqueue_stub.py:1936] Task task3 failed to execute. This task will retry in 0.128 seconds<br />
WARNING  2012-03-27 12:40:36,570 taskqueue_stub.py:1936] Task task4 failed to execute. This task will retry in 0.128 seconds<br />
WARNING  2012-03-27 12:40:36,688 taskqueue_stub.py:1936] Task task3 failed to execute. This task will retry in 0.256 seconds<br />
WARNING  2012-03-27 12:40:36,701 taskqueue_stub.py:1936] Task task4 failed to execute. This task will retry in 0.256 seconds<br />

As you can see, no stack traces.

First we tried searching the internet for a solution, but apart from many others looking for help, we did not find the fix we needed. So there was no other option, as to debug the Google App Engine dev_server stack ourselves.

After a while we found that for some reason the development server stopped launching the task urls on the correct location. For some reason it resolved its own hostname and tried to access the RequestHandler with the hostname instead of on the ip address it is serving our app. Which did not work because the hostname resolves locally to 127.0.0.1 instead of on the ip address on wich we have the development serving. On top of that it totally lost the configured port as well on which we configured the dev server.

We fixed it by adding an extra line at the following location:

<br />
root@dev:/root/testing# git diff /root/testing/google_appengine/google/appengine/api/taskqueue/taskqueue_stub_original.py /root/testing/google_appengine/google/appengine/api/taskqueue/taskqueue_stub.py<br />
diff &#8211;git a/root/testing/google_appengine/google/appengine/api/taskqueue/taskqueue_stub_original.py b/root/testing/google_appengine/google/appengine/api/taskqueue/taskqueue_stub.py<br />
index df3b6a7..305167a 100644<br />
&#8212; a/root/testing/google_appengine/google/appengine/api/taskqueue/taskqueue_stub_original.py<br />
+++ b/root/testing/google_appengine/google/appengine/api/taskqueue/taskqueue_stub.py<br />
@@ -1826,6 +1826,7 @@ class _TaskExecutor(object):</p>
<p>       connection_host, = header_dict.get(&#8216;host&#8217;, [self._default_host])<br />
+      connection_host = self._default_host<br />
       if connection_host is None:<br />
         logging.error(&#8216;Could not determine where to send the task &quot;%s&quot; &#8216;<br />
                       &#8216;(Url: &quot;%s&quot;) in queue &quot;%s&quot;. Treating as an error.&#8217;,<br />

Performing remote API calls in a reliable way.

Mar 15, 2012   //   by Geert Audenaert   //   Blog, Tech  //  No Comments

I just finished coding a new version of Mobidick. This is a sample Rogerthat service which our customers use to try out & test drive our messaging APIs. I use some elegant and new techniques to perform API calls in a very reliable way. I’m pretty pleased with the result, so felt like blogging about it.

My definition of performing API calls in a reliable way: retriable API calls to remote systems getting an idempotent result

It seems obvious, and all systems should interoperate like that, but actually it is not so obvious at all. This is mainly because client and server must cooperate to get this behavior.

For example, on the client side you cannot submit a retriable API call from within a synchronous HTTP request processing, because the client invoking the HTTP request expects a result within a few seconds. Hence making an API call to a remote system reliably, requires to execute it from an out-of-context system (e.g. a queueing server) which is preferably transactional.

On the other hand, on the server side you must be able to deal with receiving single API calls multiple times, preventing double execution of the invoked API, yet returning the correct return values to the client.

There are two options to solve this on the server:

  • An API result cache
  • Implementing all functionality in the server in an idempotent way

For the Rogerthat server we opted for the API result cache method. The reason why we choose this method is because it is almost impossible to write a messaging system idempotently. Also the API result cache approach results in much easier coding, which makes our developers more productive.

For example, when I send two identical messages to my colleague Carl, he must receive them both. An idempotent implementation of the messaging system would prevent that. On the other hand, if I have to submit a single message twice due to eg. networking troubles, I only want Carl to receive the message once.

Indeed we cache every API call invocation and its calculated result for some time. If we receive an API call twice, we do not process it again, thereby avoiding the side effects of the call invocation. Instead we just return the cached result.

That’s why we opted for JSON-RPC which adds call id to every single API invocation.

Executing the following call twice, results in 1 message sent to Carl, because the server cashes the result based on the id that the client put on the API call.

<br />
{<br />
  &#8216;id&#8217;: &#8217;8CC77A45-7898-4DC9-8D52-6D3B7871BF98&#8242;,<br />
  &#8216;method&#8217;: &#8216;send_message&#8217;,<br />
  &#8216;params&#8217;: {<br />
    &#8216;subject&#8217;: &#8216;long time no see&#8217;,<br />
    &#8216;message&#8217;: &#8216;Hi Carl,\n\nits been a while since we saw each other\n\nShall we grab dinner together this evening?&#8217;<br />
  }<br />
}<br />

That is ok, the server is protected to send a message only once, even if the API caller was unable to receive the result of the first invocation of the API call. So Carl’s inbox won’t be spammed in case of trouble, and I’m sure he will get the message, because I don’t have to be afraid to retry the API call in troublesome situations.

Now I only have to make sure that my client code also plays along nicely.

If you know Google App Engine, you will have noticed that Mobidick is a Google App Engine app. In fact it is created in the python version of Google App Engine with the python 2.7 runtime.

Google App Engine makes it quite easy to implement the desired client behavior to call a remote API reliably.

Eg: Submitting the send_message API call correctly.

<br />
class SendMessageHandler(webapp2.RequestHandler):</p>
<p>    def post(self):<br />
        # Get post data<br />
        subject = self.request.get(&quot;subject&quot;)<br />
        message = self.request.get(&quot;message&quot;)<br />
        # Store message locally, and then submit to remote transmitting system<br />
        def trans():<br />
            msg = Message()<br />
            msg.subject = subject<br />
            msg.message = message<br />
            msg.put()<br />
            deferred.defer(_send_message_to_carl, msg, str(uuid.uuid4())<br />
        xg_on = db.create_transaction_options(xg=True)<br />
        db.run_in_transaction_options(xg_on, trans)</p>
<p>def _send_message_to_carl(msg, json_rpc_id):<br />
    json_rpc_call = {&#8216;id&#8217;: json_rpc_id,<br />
                     &#8216;method&#8217;: &#8216;send_message&#8217;,<br />
                     &#8216;params&#8217;: {&#8216;subject&#8217;:msg.subject, &#8216;message&#8217;: msg.message} }<br />
    json_rpc_result = perform_http_json_rpc_request(json_rpc_call)<br />
    do_something_with_the_result(json_rpc_result)<br />

As can you see, it does not require a lot of energy from the developer to make the API call idempotent and reliable.

So, where is the magic ? The magic lies in the transactional scheduling of a task. The Python version of GAE supplies us with the magical way of scheduling a task through the deferred library, which makes it very convenient to perform out-of-context actions. Also, GAE automatically retries tasks when they fail. When perform_http_json_rpc_request fails, it will be executed again by GAE until it succeeds.

Useful links:

Rogerthat product: http://www.rogerthat.net
Rogerthat web application: https://rogerth.at
Mobidick: https://mobidick-cloud.appspot.com/
json-rpc: http://json-rpc.org/
Google App Engine: http://code.google.com/appengine/
Transactions in GAE: http://code.google.com/appengine/docs/java/datastore/transactions.html
Background work with deferred library: http://code.google.com/appengine/articles/deferred.html

Accessing the Rogerthat API from mono.

Jan 27, 2012   //   by Geert Audenaert   //   Blog, Tech  //  No Comments

TechShore.EU today reported that he could not access the Rogerthat API through the opensource .NET API stubs from his ubuntu 11.10.

After some digging Peter discovered the root cause of the problem. The Rogerthat SSL certificate was not trusted by his mono installation.

He resolved the problem by executing

certmgr -ssl https://rogerth.at/api/1

and answering ‘y’ on every question. As a result the mono installation trusts the complete certificate chain used by the Rogerthat API.

How to mute Rogerthat sound on iPhone 4 / iOS 5

Jan 20, 2012   //   by Carl D'Halluin   //   Blog, News, Tech  //  No Comments

Due to a bug in Apple iOS 5, it is not possible for applications to retrieve the state of the hardware mute button on your iPhone 4.

It has been confirmed by Apple that this is indeed not supported.

A workaround to silence the Rogerthat application is to mute your Media Volume as follows:

  1. Mute your ringer sound by toggling the hardware mute switch
  2. Mute your media sound using the following steps
    • Double click your home button
    • Scroll the bottom pane completely to the left
    • Minimize the volume. Check the screenshot

Retrieving the state of the hardware mute button was possible on an iPhone 4 having the iOS 4 operating system.

We asked Apple to reintroduce this functionality in iOS 5 and will include this in the Rogerthat application as soon as the Apple functionality becomes available.

Processing iPhone or iPad Crash Reports

Dec 13, 2011   //   by Carl D'Halluin   //   Blog, Tech  //  No Comments

When iPhone or iPad apps crash, you typically see crash information such as

<br />
Thread 5 name:  Dispatch queue: com.apple.root.default-priority<br />
Thread 5 Crashed:<br />
0   libobjc.A.dylib               	0x333a6c98 objc_msgSend + 16<br />
1   rogerthat                     	0&#215;00028066 0&#215;1000 + 159846<br />
2   rogerthat                     	0&#215;00056876 0&#215;1000 + 350326<br />
3   rogerthat                     	0x0006eaa2 0&#215;1000 + 449186<br />
4   rogerthat                     	0x000c8224 0&#215;1000 + 815652<br />
5   rogerthat                     	0x0002b69a 0&#215;1000 + 173722<br />
6   rogerthat                     	0x0002c052 0&#215;1000 + 176210<br />
7   rogerthat                     	0x0002b336 0&#215;1000 + 172854<br />
8   rogerthat                     	0x00025de8 0&#215;1000 + 151016<br />
&#8230;<br />

This crash information can be found in XCode – Organizer – Device Logs.
These crash reports are pretty unusable unless you “symbolicate” them.

Here is a small tutorial on how to do this:

  • Build your iPhone app using Build and Archive in the XCode Build menu
  • In XCode Organizer, select your app in Archived Applications
  • Select the appropriate build and right click Show in Finder
  • Apple-C to copy this folder
  • In your terminal cd to that folder (Apple-V to paste)
  • locate symbolicatecrash – On my Mac it is in
    /Developer/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks/DTDeviceKit.framework/Versions/A/Resources/symbolicatecrash
  • Execute the symbolicatecrash command and enjoy a readable crash report

<br />
$pwd<br />
/Users/carl/Library/Application Support/Developer/Shared/Archived Applications/97868891-2237-46CA-A87E-66E6E7B7A2DF.apparchive</p>
<p>$ls<br />
ArchiveInfo.plist	rogerthat.app		rogerthat.app.dSYM</p>
<p>$locate symbolicatecrash<br />
/Developer/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks/ DTDeviceKit.framework/Versions/A/Resources/symbolicatecrash</p>
<p>$/Developer/Platforms/iPhoneOS.platform/Developer/Library/ PrivateFrameworks/DTDeviceKit.framework/Versions/A/Resources/ symbolicatecrash ~/Downloads/stack.txt</p>
<p>&#8230;</p>
<p>Thread 5 name:  Dispatch queue: com.apple.root.default-priority<br />
Thread 5 Crashed:<br />
0   libobjc.A.dylib   0x333a6c98<br />
                      objc_msgSend + 16</p>
<p>1   rogerthat     0&#215;00028066<br />
                  -[NSMutableDictionary(MCTTools2) setString:forKey:]<br />
                  (MCTJSONUtils.m:168)</p>
<p>2   rogerthat     0&#215;00056876<br />
                  -[MCTIntent setString:forKey:]<br />
                  (MCTIntent.m:123)</p>
<p>3   rogerthat     0x0006eaa2<br />
                  -[MCTIdentityStore saveAvatarWithData:]<br />
                  (MCTIdentityStore.m:219)</p>
<p>4   rogerthat     0x000c8224<br />
                  -[MCTGetAvatarResponseHandler handleResult:]<br />
                  (MCTGetAvatarResponseHandler.m:66)</p>
<p>5   rogerthat     0x0002b69a<br />
                  -[MCTRPCProtocol processIncomingResponse:]<br />
                  (MCTRPCProtocol.m:201)</p>
<p>6   rogerthat     0x0002c052<br />
                  -[MCTRPCProtocol processIncomingMessagesDict:]<br />
                  (MCTRPCProtocol.m:260)</p>
<p>7   rogerthat     0x0002b336<br />
                  -[MCTRPCProtocol processIncomingMessagesStr:]<br />
                  (MCTRPCProtocol.m:321)</p>
<p>8   rogerthat     0x00025de8<br />
                  -[MCTCommunicationManager communicationFinishedWithLoop:]<br />
                  (MCTCommunicationManager.m:368)</p>
<p>&#8230;</p>
<p>

Problems visiting https:// sites on your Android mobile browser?

Sep 16, 2011   //   by Carl D'Halluin   //   Blog, News, Tech  //  1 Comment

On a number of mobile data networks, and for certain types of Android phones, it is impossible to visit SSL sites using the builtin mobile web browser.

What you typically experience:

  • When your phone is connected to Wi-Fi, you can visit https:// sites without problems
  • When Wi-Fi is disabled or out of reach, your phone will use mobile data (typically 3G or Edge) to connect to the internet. When visiting a https:// site, the browser window stays empty, and the browser immediately stops loading the page.

My specific configuration:

  • Phone: Google Nexus One (2010)
  • Android version: 2.3.4 “Gingerbread”
  • Country: Belgium
  • Mobile data provider: Mobistar
  • Network type: Edge or 3G

The same problem has been reported on many mobile data networks in various countries.

The solution is simple: disable the APN Proxy settings on your phone. On my Nexus One with Android 2.3.4 this is the menu sequence:

  • Open menu
  • Select Settings
  • Select Wireless & networks
  • Select Mobile networks
  • Select Access Point Names
  • Select your active access point
  • Clear the values for Proxy and Port
  • Press menu button and select Save