Showing posts with label MapView. Show all posts
Showing posts with label MapView. Show all posts

Thursday, June 13, 2013

Android MapsV2 Module Sample Code in Titanium Mobile Alloy

With the introduction of SDK 3.0, a new framework called Alloy had been integrated with Titanium. This framework uses model-view-controller architecture to break down your application code. While it is fairly simple to learn the new framework, I encountered a bit of slowdown when trying to use the new Google Maps Android v2 module in it. To help save a lot of time, I'll demonstrate how I used the  map module on the new framework.

First, you need to download the map module from here. After you have downloaded the zip file, you need to put the extracted contents on the root folder of your application.


You can also put the module in the Titanium SDK Home Directory (but for me, I prefer to use the application folder).

After placing the module on the proper folder, you need to edit the tiapp.xml file on your project root. Find the <modules/> tag and update it like below:
1:    <modules>  
2:         <module platform="android" version="2.1.0">ti.map</module>  
3:    </modules>  

Find the <android xmlns:android="http://schemas.android.com/apk/res/android"/> tag and update it as well:
1:  <android xmlns:android="http://schemas.android.com/apk/res/android">  
2:      <manifest>  
3:        <!-- Allows the API to download data from Google Map servers -->  
4:        <uses-permission android:name="android.permission.INTERNET"/>  
5:        <!-- Allows the API to cache data -->  
6:        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>  
7:        <!-- Use GPS for device location -->  
8:        <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>  
9:        <!-- Use Wi-Fi or mobile connection for device location -->  
10:        <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>  
11:        <!-- Allows the API to access Google web-based services -->  
12:        <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>  
13:        <!-- Specify OpenGL ES 2.0 as a requirement -->  
14:        <uses-feature android:glEsVersion="0x00020000" android:required="true"/>  
15:        <!-- Replace com.domain.appid with your application ID -->  
16:        <uses-permission android:name="<com.domain.appid>.permission.MAPS_RECEIVE"/>  
17:        <permission android:name="<com.domain.appid>.permission.MAPS_RECEIVE"  
18:          android:protectionLevel="signature"/>  
19:        <application>  
20:          <!-- Replace "PASTE YOUR GOOGLE MAPS API KEY HERE" with the Google API key you obtained -->  
21:          <meta-data android:name="com.google.android.maps.v2.API_KEY"  
22:            android:value="PASTE YOUR GOOGLE MAPS API KEY HERE"/>  
23:        </application>  
24:      </manifest>  
25:    </android>  

Remember to set your api key on the android:value property of the meta-data tag on the manifest section of your tiapp.xml file. Also, change the <com.domain.appid> strings on that same section with your application id found between the <id></id> tags in the tiapp.xml file.

An alloy application framework code is divided into four parts. Each part can be located in its corresponding folder under the app directory. For my sample application, I have no need for a model so you can see that it's folder is empty.


Since all alloy application start with the index, you can see the controllers, views, and styles had been created. I don't need customise the view so I just removed the sample code from it:

1:  <Alloy>  
2:       <Window class="container">  
3:       </Window>  
4:  </Alloy>  


To instantiate the module, just use the require method. In my sample application, I placed it in the index controller. The file can be found inside the app/controllers/ directory. The code for my index.js file is as follows:

1:  var MapModule = require('ti.map');  
2:  var mapview = MapModule.createView({  
3:       mapType : MapModule.NORMAL_TYPE,  
4:       region: {  
5:            latitude:33.74511,   
6:            longitude:-84.38993,  
7:      latitudeDelta:0.01,   
8:      longitudeDelta:0.01  
9:    },  
10:    top : 0,  
11:    left : 0,  
12:    right : 0,  
13:    bottom : 0,  
14:    animate:true,  
15:    regionFit:true  
16:  });  
17:  $.index.add(mapview);  
18:  $.index.open();  

Just adding the code above on the index controller will already add the MapView on the application window.  If you need more info on the MapView, just consult the API docs.

To see the full source of my sample application go here

MapView Transparency Bug on Titanium Android

While using the new MapView module for android, I noticed that the view becomes blank when it is animated. Even when I tried to refresh the view, the map would remain to be invisible (or seems to be located at the background).

At first, I thought it was the drawer menu widget that I was using. However, as I looked further, I was able to confirm that any animation that moves the MapView on the screen causes it to become invisible (like my sample below):

View code:
1:  <Alloy>  
2:       <Window class="container">  
3:            <View id="mainwindow" top="0" left="0" right="0" bottom="0" backgroundColor="white" onClick="doClick">  
4:            </View>  
5:       </Window>  
6:  </Alloy>  

Controller code:
1:  var MapModule = require('ti.map');  
2:  var mapview = MapModule.createView({  
3:       mapType : MapModule.NORMAL_TYPE,  
4:       region: {  
5:            latitude:33.74511,   
6:            longitude:-84.38993,  
7:      latitudeDelta:0.01,   
8:      longitudeDelta:0.01  
9:    },  
10:    top : '50dp',  
11:    left : 0,  
12:    right : 0,  
13:    bottom : 0,  
14:    animate:true,  
15:    regionFit:true  
16:  });  
17:  $.mainwindow.add(mapview);  
18:  function doClick(e) {   
19:    $.mainwindow.animate({  
20:         left : '300dp',  
21:         top : 0,  
22:         right : 0,  
23:         bottom : 0  
24:    });  
25:  }  
26:  $.index.open();  

To check if the problem is rooted at the native android sdk, I created a similar scenario on a native android application. When I was not able to encounter the same problem,  I then tried to find a workaround for this bug.

After a lot of searching, I finally found out that using hardware acceleration on the application would help in bringing back the MapView. So, going to the Android manifest, you need to find the application tag and add the property to enable hardware acceleration on your application:

1:  <application android:icon="@drawable/appicon"  
2:            android:label="sample" android:name="SampleApplication"  
3:            android:debuggable="false"  
4:            android:hardwareAccelerated="true">  

Please note that using this solution, the MapView may still disappear a bit while the view is animating, but it comes back again after the animation finishes.