Showing posts with label davistechyinfo. Show all posts
Showing posts with label davistechyinfo. Show all posts
Testing Your Apps with AWS Device Farm
Recently, I've been on a mission to enhance the quality of the tests in the Android applications that I work on. To that end, I was introduced to the AWS Device Farm, a cloud based app testing platform.
Android Devs Listen Up!
So listening to podcasts used to be the "thing", then it wasn't the "thing" anymore, and now it's back to being the "thing" to do. So with that in mind I thought I'd share some of my favorite podcasts for Android developers.
Conquering Cyclomatic Complexity
Have you ever received a warning about Cyclomatic Complexity while working with a class in Android Studio? Would you like to know how to fix it? If yes, keep reading...
Android: Custom Gson Deserialization
So here's the scenario you have a JSON Object that contains a list of objects. Each one of the objects in the primary JSON Object also contain a list of objects. So for demonstration purposes we will use a car with a list of seats and each seat has a list of buckles (Car -> Seats -> Buckles). Completely random example, yes I know.
So if you have the use case where you don't want to deserialize any seats that don't have buckles this is how you can do it using a Custom GSON Deserializer.
So if you have the use case where you don't want to deserialize any seats that don't have buckles this is how you can do it using a Custom GSON Deserializer.
Android: Location Updates with the FusedLocationApi
If you want to retrieve the user's location in your Android application you can take advantage of Google's FusedLocationApi. Essentially you establish a connection to the GoogleApiClient and then set up a LocationRequest. It's up to you to configure the rate at which you would like to receive updates. Here is an example of using the API:
import android.app.Activity;
import android.content.Intent;
import android.location.Location;
import android.net.Uri;
import android.os.Bundle;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class MainActivity extends Activity implements
LocationListener,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
private static final long ONE_MIN = 1000 * 60;
private static final long TWO_MIN = ONE_MIN * 2;
private static final long FIVE_MIN = ONE_MIN * 5;
private static final long POLLING_FREQ = 1000 * 30;
private static final long FASTEST_UPDATE_FREQ = 1000 * 5;
private static final float MIN_ACCURACY = 25.0f;
private static final float MIN_LAST_READ_ACCURACY = 500.0f;
private LocationRequest mLocationRequest;
private Location mBestReading;
private GoogleApiClient mGoogleApiClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!servicesAvailable()) {
finish();
}
setContentView(R.layout.activity_main);
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(POLLING_FREQ);
mLocationRequest.setFastestInterval(FASTEST_UPDATE_FREQ);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
@Override
protected void onResume() {
super.onResume();
if (mGoogleApiClient != null) {
mGoogleApiClient.connect();
}
}
@Override
protected void onPause() {
super.onPause();
if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
@Override
public void onLocationChanged(Location location) {
// Determine whether new location is better than current best
// estimate
if (null == mBestReading || location.getAccuracy() < mBestReading.getAccuracy()) {
mBestReading = location;
if (mBestReading.getAccuracy() < MIN_ACCURACY) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
}
}
@Override
public void onConnected(Bundle dataBundle) {
// Get first reading. Get additional location updates if necessary
if (servicesAvailable()) {
// Get best last location measurement meeting criteria
mBestReading = bestLastKnownLocation(MIN_LAST_READ_ACCURACY, FIVE_MIN);
if (null == mBestReading
|| mBestReading.getAccuracy() > MIN_LAST_READ_ACCURACY
|| mBestReading.getTime() < System.currentTimeMillis() - TWO_MIN) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
// Schedule a runnable to unregister location listeners
Executors.newScheduledThreadPool(1).schedule(new Runnable() {
@Override
public void run() {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, MainActivity.this);
}
}, ONE_MIN, TimeUnit.MILLISECONDS);
}
}
}
@Override
public void onConnectionSuspended(int i) {
}
private Location bestLastKnownLocation(float minAccuracy, long minTime) {
Location bestResult = null;
float bestAccuracy = Float.MAX_VALUE;
long bestTime = Long.MIN_VALUE;
// Get the best most recent location currently available
Location mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (mCurrentLocation != null) {
float accuracy = mCurrentLocation.getAccuracy();
long time = mCurrentLocation.getTime();
if (accuracy < bestAccuracy) {
bestResult = mCurrentLocation;
bestAccuracy = accuracy;
bestTime = time;
}
}
// Return best reading or null
if (bestAccuracy > minAccuracy || bestTime < minTime) {
return null;
}
else {
return bestResult;
}
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
private boolean servicesAvailable() {
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (ConnectionResult.SUCCESS == resultCode) {
return true;
}
else {
GooglePlayServicesUtil.getErrorDialog(resultCode, this, 0).show();
return false;
}
}
}
Android: Determining if a Wearable Device is Connected
I'm playing around with developing an application that integrates with the new Android Wear API. In my case I don't want to perform certain actions locally if a wearable device is connected. So this is how you can detect if a device is connected. You would have this code included in the Main Activity of your primary (phone) application:
Grails: Functional Testing with Geb and Spock
Functional testing allows you to execute HTTP requests against your running application and verify if it's performing the desired behavior.
Since Grails doesn't ship with any direct support for functional testing (using Grails 2.2.4) I decided to use a common configuration of Geb with Spock for my testing needs. My configuration files are included below. I had to modify BuildConfig.groovy and then include a separate configuration file for Geb.
BuildConfig.groovy
repositories {
mavenRepo "http://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-support"
}
def gebVersion = "0.9.2"
def seleniumVersion = "2.35.0"
dependencies {
test "org.seleniumhq.selenium:selenium-chrome-driver:$seleniumVersion"
test "org.spockframework:spock-grails-support:0.7-groovy-2.0"
test "org.gebish:geb-spock:$gebVersion"
test "org.seleniumhq.selenium:selenium-support:2.40.0"
}
plugins {
test ":geb:$gebVersion"
test (":spock:0.7") {
exclude "spock-grails-support"
}
}
The tests and config files are stored in the test/functional folder of the main application. In the primary functional folder you can place your GebConfig.groovy file. There are various configuration options available to you. I prefer to use a very simple version, consisting of the following:
GebConfig.groovy
import org.openqa.selenium.chrome.ChromeDriver
reportsDir = "target/geb-reports"
driver = { new ChromeDriver() }
You will also need to install the ChromeDriver. Info available here.
Once that's done, you should define some Geb Pages that represent the corresponding gsp pages in your application. I typically define three key components: the url, the at closure, and the content closure. These elements will be used in your Spock Specification to navigate to the desired page in your application, verify that you are at the correct page and then interact with elements on the page that you define in the content closure.
Sample Page
import geb.Page
class LoginPage extends Page {
static url = "login/auth"
static at = { title == "Login" }
static content = {
loginForm { $("#loginForm") }
loginButton { $("#loginButton") }
registerLink { $("a[href*='register/index']") }
}
}
Sample Spec
import geb.spock.GebReportingSpec
import spock.lang.Stepwise
@Stepwise
class LoginSpec extends GebReportingSpec {
def "invalid login"() {
given: "I am at the login page"
to LoginPage
when: "I am entering invalid password"
loginForm.j_username = "me@gmail.com"
loginForm.j_password = "ioguffwf"
loginButton.click()
then: "I am being redirected to the login page"
at LoginPage
!loginForm.j_username
!loginForm.j_password
}
def "admin login"() {
given : "I am at the login page"
to LoginPage
when: "I am entering valid username and password"
loginForm.j_username = "me@gmail.com"
loginForm.j_password = "me"
loginButton.click()
then: "I am being redirected to the homepage"
at HomePage
}
}
Spock specifications are very simple to read and should be written in such a way that it's very clear what you are attempting to test and verify. In this case, the LoginSpec, the specification has only two methods which are executed in order. The first makes sure that when a user enters invalid login credentials they are redirected back to the log in page. The second verifies that they are taken to the HomePage when the login succeeds.
In order to run your functional tests you can use the following commands:
grails test-app functional: -https grails test-app -clean functional: LoginSpec -https
I add the -https flag because my application has support for https and I want to be able to test that functionality as well.
Happy testing!
Android Annotations: Brief Overview and a Simple Example
Android Annotations is a project which allows you to use simple Java Annotations in your Android classes and have the compiler generate some of the "boilerplate code" for you. I have not noticed any overhead in the application's performance so far and I really like how neat the code is, when compared to some of the default code that is typical in Android applications.
Here is an example of creating an activity and then performing a simple operation using a bean to load data:
So what you'll notice in the code is that it's very clear what this Activity is doing, no need to scroll through lists of Views being initialized and endless availability checks. Also, the click listeners that are normally splattered throughout the code is contained in a simple method with the @Click annotation. Here you just define the resource id of the item that you would like to associate with the click event and then a method to handle the click.
Furthermore, this Activity references a view in the R.layout.main layout file, without having to define the typical onCreate() method. It also defines which menu file it's going to use with the @OptionsMenu annotation. Pretty simple, right? In a future post I will show additional examples of how using AndroidAnnotations makes your code more maintainable. Have you tried this library yet? If so, please let me know what you think. Curious to find out what others think of it.
Here is an example of creating an activity and then performing a simple operation using a bean to load data:
@EActivity(R.layout.main)
@OptionsMenu(R.menu.main_menu)
@Fullscreen
public class MainActivity extends Activity {
@Bean(MyAPIImpl.class)
MyAPI mAPI;
@AfterInject
void loadData() {
mAPI.getData();
}
@Click(R.id.startButton)
void startClicked() {
NextActivity_.intent(this).start();
}
}
So what you'll notice in the code is that it's very clear what this Activity is doing, no need to scroll through lists of Views being initialized and endless availability checks. Also, the click listeners that are normally splattered throughout the code is contained in a simple method with the @Click annotation. Here you just define the resource id of the item that you would like to associate with the click event and then a method to handle the click.
Furthermore, this Activity references a view in the R.layout.main layout file, without having to define the typical onCreate() method. It also defines which menu file it's going to use with the @OptionsMenu annotation. Pretty simple, right? In a future post I will show additional examples of how using AndroidAnnotations makes your code more maintainable. Have you tried this library yet? If so, please let me know what you think. Curious to find out what others think of it.
Android: IntelliJ IDEA/Android Studio Quick Tip
I've started using IntelliJ as my IDE of choice for developing backend APIs and Android applications. One really nice feature, which is also available in Android Studio, is the option to create strings.xml values on the fly. All you need to do is type the name of the desired string resource and then the "bulb" icon will appear asking you if you want to create that resource. Super simple, but extremely convenient for those times when you are editing a lot of xml files in Android.
Configuring Dev and Prod Environments in Spring 3.1
Recently I have been exploring the Spring MVC Framework using on Spring 3.1. Based on my Grails experience I was surprised by the amount of manual configuration that is required. Nevertheless, I thought I would quickly share how to configure development and production environments in your application. Spring 3.1 introduced what is known as Profiles, which allow the developer to create various bean definitions to be used in different environments.
For instance, in order to use a different database for your dev and prod environments you could configure your sevlet-context.xml file with the following:
Then in your web.xml file you would have the following if you were deploying for the dev environment:
It's just that simple...
For instance, in order to use a different database for your dev and prod environments you could configure your sevlet-context.xml file with the following:
Then in your web.xml file you would have the following if you were deploying for the dev environment:
It's just that simple...
Grails: Cannot create JDBC driver of class 'com.mysql.jdbc.Driver' for connect URL 'jdbc:hsqldb:mem:grailsDB'
Recently received the following error when attempting to deploy a new war file on my Glassfish server:
I typed grails rstaging war instead of grails staging war. This is just another example of extremely useful error messages that I've encountered while developing for Grails.
Cannot create JDBC driver of class 'com.mysql.jdbc.Driver' for connect URL 'jdbc:hsqldb:mem:grailsDB'The solution to the issue however, has nothing to do with MySQL and drivers whatsoever. The problem was that I mistyped the environment name when creating the war file.
I typed grails rstaging war instead of grails staging war. This is just another example of extremely useful error messages that I've encountered while developing for Grails.
First Android Application Released - Word Crank
So with all of the free time that I have (smirk), I managed to create an Android Game along with my brother, called Word Crank. Word Crank is a simple, yet addictive game of creating words as letters fall from above. Check it out and leave me feedback. Thanks.
Git Merging
Another helpful tool in working with Git repositories is the git mergetool command. This provides you with a graphical interface for merging conflicts. What's nice about this tool is that you can see all of the differences in the remote file and the local file and you can go through each and choose the change that you want to keep. Very nice!
Creating a Texture in OpenGL ES 1.0
I have recently been learning to use OpenGL ES on Android. I know that many devices currently support OpenGL ES 2.0, but I wanted to start with 1.0 that is supported everywhere. To that end I will be making a series of posts that contain various bits of code that I have learned along the way that might be useful to others.
So, this is how you can create a texture in OpenGL ES 1.0:
You can then use the textureId to bind the texture and draw it on the OpenGLSurfaceView.
So, this is how you can create a texture in OpenGL ES 1.0:
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.item); int[] textureIds = new int[1]; gl.glGenTextures(1, textureIds, 0); textureId = textureIds[0]; gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId); GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE); gl.glBindTexture(GL10.GL_TEXTURE_2D, 0); bitmap.recycle();
You can then use the textureId to bind the texture and draw it on the OpenGLSurfaceView.
Removing jar files from your Grails war
Recently I encountered a situation where a plugin was bringing in a version of a jar file that was causing my application to misbehave. In order to fix this issue I had to remove the errant jar file from the final build. This is the code that you can use to do that. You have to place this code snippet in your BuildConfig.groovy. Hope this helps someone else.
grails.war.resources = { stagingDir ->
delete(file:"${stagingDir}/WEB-INF/lib/<name>.jar")
}
Using awk on the Command Line to Parse Files
I needed to format a file that contained a list of words with their accompanying definitions. I didn't need the definitions and wanted to put an 'item' tag around each word. awk to the rescue!
The Command:
The Command:
awk '{print "- "$1"
"}' < words.xml
I have this stored in the words.xml file:
BAD something bad
BAG to put into a bag
BAH intj. expressing disgust
BAL type of shoe (balmoral)
BAM to strike with a dull sound
BAN to prohibit/Rumanian coin
After running the command, I get:
<item>BAD</item>
<item>BAG</item>
<item>BAH</item>
<item>BAL</item>
<item>BAM</item>
<item>BAN</item>
Thanks awk!
Updated: Mocking Hibernate Create Criteria in Grails' Unit Test with GMock
Using the GMock Library I have updated my unit tests to mock out the create criteria methods the following way:
You need to add the following to the top of the unit test file with the import statements:
Also add the following to your BuildConfig.groovy:
I learned this from the following blog post: http://adhockery.blogspot.com/2010/01/using-gmock-to-complement-grails.html
void testSomeFunction() {
def results = []
def mockCriteria = mock() {
list(instanceOf(Closure)).returns(results)
}
mock(Book).static.createCriteria().returns(mockCriteria)
play {
assertEquals null, bookService.getDefaultBook(null)
}
}
You need to add the following to the top of the unit test file with the import statements:
import org.gmock.* import static org.hamcrest.Matchers.* @WithGMock
Also add the following to your BuildConfig.groovy:
dependencies {
test "org.gmock:gmock:0.8.0"
test "org.hamcrest:hamcrest-all:1.0"
}
I learned this from the following blog post: http://adhockery.blogspot.com/2010/01/using-gmock-to-complement-grails.html
3 Tips to Help Avoid the Hibernate Flush
When using Grails, the default behavior of Hibernate is to do a flush before queries, at the end of requests, and pretty much whenever Hibernate feels like it. So here are three tips that can help you avoid some of the flushing and/or at the very least decrease the number of database connections that Hibernate attempts to get:
- Use read() function when possible: If you are only going to read some field of a domain object and will make no changes to it, then just use object.read(), instead of the get() method
- Make sure your services are only transactional if they need to be, so if you are not updating, saving, or deleting records in the db chances are you do not need your Service to be transactional
- If you do have some transactional logic, put it inside a domain.withTransaction {} closure instead of making the entire function or class transactional
Configuration of DataSource.groovy for Highly Concurrent Grails Application
In developing a highly concurrent Grails Application, I ran into an issue where many connections were being created to the database and were subsequently not released. After reading several blog posts it seems that the library used to handle the connection pooling was not designed for highly concurrent systems. I found that using the following setup in your DataSource.groovy file eliminates the stale connection issue and allows a high level of concurrency.
dataSource {
pooled = true
driverClassName = "com.mysql.jdbc.Driver"
dialect = "org.hibernate.dialect.MySQL5InnoDBDialect"
properties {
maxActive = 50
maxIdle = 10
initialSize = 10
minEvictableIdleTimeMillis = 10000
timeBetweenEvictionRunsMillis = 20000
maxWait = 10000
validationQuery = "/* ping */"
testWhileIdle = true
numTestsPerEvictionRun = 3
testOnBorrow = true
}
}
Hope this can help someone else.
dataSource {
pooled = true
driverClassName = "com.mysql.jdbc.Driver"
dialect = "org.hibernate.dialect.MySQL5InnoDBDialect"
properties {
maxActive = 50
maxIdle = 10
initialSize = 10
minEvictableIdleTimeMillis = 10000
timeBetweenEvictionRunsMillis = 20000
maxWait = 10000
validationQuery = "/* ping */"
testWhileIdle = true
numTestsPerEvictionRun = 3
testOnBorrow = true
}
}
Hope this can help someone else.
Subscribe to:
Posts (Atom)








