TurboManage

David Chandler's Journal of Java Web and Mobile Development

  • David M. Chandler


    Web app developer since 1994 now working for Google and residing in Atlanta with the wife of my youth and our five children. My current side project is a not-for-profit startup using GWT on AppEngine. In my "spare" time, I take pictures, preferably of Rocky Mountain National Park.

  • Subscribe

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 134 other followers

  • Sleepless Nights…

    May 2012
    S M T W T F S
    « Apr    
     12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
  • Blog Stats

    • 344,154 hits

Archive for the ‘Android’ Category

Troubleshooting App Engine-connected Android projects with c2dm

Posted by David Chandler on May 18, 2012

Google Plugin for Eclipse has a wizard to create an Android project with App Engine back end including client push (c2dm). The official tutorial is quite good, but after spending the better part of a day trying to get the Cloud Tasks sample up and running again, I thought it might be useful to post a few tips.

General Tips

  • Sign up for c2dm first. Remember the package name and use it when running the Eclipse wizard! The package name is required, and once you choose the package name on c2dm sign-up, it is nowhere visible later. Be patient–it may take an hour or even a day to activate your account.
  • Sign in to Eclipse with the c2dm account name you’ll use (see lower left corner–if not visible, you need Google Plugin for Eclipse). It’s easy to forget this, but Debug As | Local App Engine Connected Project requires you to be signed in.

Run on a Phone With the GAE Dev Server

In this scenario, the phone and dev server must be on the same network! Easiest way is to connect to the same wi-fi router. USB cable does nothing. Be aware that most public wi-fi routers don’t allow devices to contact each other, so it will probably work best at home or on your company’s guest wi-fi network.

  • Add -bindAddress 0.0.0.0 to your Web project’s Run Configuration | Program Arguments. This will start the server listening on all addresses, not just the default localhost (which the phone can’t see).
  • When you choose Debug As | Local App Engine Connected Android Application, GPE hardcodes your machine’s IP address in assets/debugging_prefs.properties. This is where the Android app looks up the address of the server.
  • You can launch/debug the Android app and the Web app independently; however, if your server IP address changes, you must again Debug As | Local App Engine Connected Android Application in order to update the IP address in assets/debugging_prefs.properties.
  • In case you wondered, the Android and Web projects are associated in a file in the Android project. You can find it in .settings/com.google.gdt.eclipse.mobile.android.prefs. To associate a different App Engine project with an Android project, simply edit this file and refresh the project.
  • If you’re using the GWT dev mode browser plugin, you can still connect to 127.0.0.1. If you connect to the address shown in Development Mode tab (your machine’s network IP address), you may need to allow the address in the dev mode browser plugin. Click the GWT icon in the address bar to do this.
  • Make sure you log in to the Web app as the c2dm user, not the default test@example.com.

Run on a Phone Against the Production App

In the production scenario, you’re using real c2dm so the phone doesn’t have to be on wi-fi at all.

  • Edit Setup.java and change APP_NAME and SENDER_ID to match your GAE app id and c2dm account.
  • Change app id in appengine-web.xml to match your GAE app.
  • Deploy to App Engine with your c2dm account.
  • Force sign in to GAE app by going to [prod_url]/tasks/. This triggers the security constraint in web.xml to get logged in to GAE. After logging in, you’ll get an error page, but that’s OK. Then go to [prod_url]/ and Say Hello to App Engine. If logged in, you should see a success message.
  • If you’ve previously connected an account on a phone to this production app, go to GAE datastore viewer and delete all records.
  • In Eclipse, Debug as | Remote App Engine Connected Android project
  • On the phone, you’ll be prompted to connect an account. Use your c2dm account. If you have previously connected a different account, go to Menu | Accounts | Disconnect in the app and reconnect.

The CloudTasks project still has a few issues. Feel free to log them in the tracker.

Posted in Android, AppEngine, Google Web Toolkit | Leave a Comment »

Show soft keyboard automatically when EditText receives focus

Posted by David Chandler on May 2, 2012

I’ve been unpleasantly surprised at how difficult it is to find info on showing or hiding the Android soft keyboard, so I’m putting a few code snippets out here for posterity.

Problem

I have a DialogFragment with an EditText. When the dialog is shown, I want to immediately focus the EditText and show the keyboard.

Solution 1 (recommended)

Set the dialog Window’s soft input method.

public class EditNameDialog extends DialogFragment {

	private EditText editText;

	public EditNameDialog() {
		// Empty constructor required for DialogFragment
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		View view = inflater.inflate(R.layout.fragment_edit_name, container);
		editText = (EditText) view.findViewById(R.id.txt_yourName);

		// Request focus and show soft keyboard automatically
		editText.requestFocus();
		getDialog().getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE);

		return view;
	}
}

As an alternative to editText.requestFocus(), you can use the <requestFocus /> tag in the fragment’s XML layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/edit_name"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/lbl_yourName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="What is your name?" />

    <EditText
        android:id="@+id/txt_yourName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10" >
		<requestFocus />
    </EditText>

</LinearLayout>

Setting the Window’s soft input method is definitely the easiest way to show the keyboard. However, in some circumstances, you may need to “force” it open or shut by invoking the InputMethodManager directly.

Solution 2

Invoke the InputMethodManager service.

This approach is more complicated because the input method manager ignores keyboard requests unless the EditText and the Window it’s in both have focus. So upon entering an Activity / Dialog, you need to wait until focus has settled down before you request the keyboard. You can do this by calling the InputMethodManager service in an OnFocusChangeListener, but Views can get focus before the Window itself does, so you have to wait for Window focus. There is no way that I can find to add an OnFocusChangeListener on the Window object itself, but listening for View focus and posting a Runnable seems to work:

...
		editText.setOnFocusChangeListener(new OnFocusChangeListener() {
			@Override
			public void onFocusChange(View v, boolean hasFocus) {
				editText.post(new Runnable() {
					@Override
					public void run() {
						InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
						imm.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT);
					}
				});
			}
		});
		editText.requestFocus();
...

This solution is not recommended because it may be buggy, but illustrates using post() to wait for the UI to settle, which may be useful in other circumstances. Note that this solution won’t work with the requestFocus tag in the layout XML because in that case, the EditText receives focus before the OnFocusChangeListener has been registered. Therefore, in the example above, we programmatically request focus after adding the listener.

Bad solutions

You can set the attribute android:windowSoftInputMode=”stateVisible” for your activity in AndroidManifest.xml. However, in the case of a DialogFragment, that will show the keyboard in the Activity’s window, which is behind the Window associated with the Dialog in the DialogFragment.

In order to get around possible Window / View focus bugs, you can use postDelayed() with a number of milliseconds to post a Runnable; however, hard-coded delays are never recommended because they may introduce unpredictable behavior under different conditions / different devices.

Summary

Ordinarily, the soft keyboard default behavior should be sufficient; however, when you programmatically focus on an EditText, you can set the Window’s soft input method to show the keyboard.

Posted in Android | 1 Comment »

Enable Geolocation in a WebView (Android)

Posted by David Chandler on April 23, 2012

HTML5 Geolocation lets you access the browser’s location information from Javascript. For a quick demo, visit google.com in a mobile browser and observe your location at the bottom of the page. Geolocation works “out of the box” in the Android browser or Chrome Beta for Android. The first time you visit a Web site that wants to know your location, the browser will prompt you to allow it.

However, if you’re writing an Android app that uses a WebView to display Web content, you must specifically enable geolocation in the WebView in order for pages that use it to work properly. To illustrate, I’ve put together a minimal Android app that uses a WebView with geolocation enabled. The easiest way to use the sample is to create a new Android Project called GeoWebView (package name com.example.webview) and then copy and replace the generated sample code with the files below.

First, the Android manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.webview"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="5" />

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".GeoWebViewActivity"
            android:label="@string/app_name"
            android:theme="@android:style/Theme.NoTitleBar" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Only two permissions are required: INTERNET and ACCESS_FINE_LOCATION. This example uses the NoTitleBar theme to display the WebView content full screen.

Next, our layout (main.xml):

<?xml version="1.0" encoding="utf-8"?>
<WebView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/webView1"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" />

Not much to it, just a WebView.

And finally, here is the complete app, consisting only of GeoWebViewActivity:

package com.example.webview;

import android.app.Activity;
import android.os.Bundle;
import android.webkit.GeolocationPermissions;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;

/**
 * A minimal WebView app with HTML5 geolocation capability
 *
 * @author David M. Chandler
 */
public class GeoWebViewActivity extends Activity {

	/**
	 * WebViewClient subclass loads all hyperlinks in the existing WebView
	 */
	public class GeoWebViewClient extends WebViewClient {
		@Override
		public boolean shouldOverrideUrlLoading(WebView view, String url) {
			// When user clicks a hyperlink, load in the existing WebView
			view.loadUrl(url);
			return true;
		}
	}

	/**
	 * WebChromeClient subclass handles UI-related calls
	 * Note: think chrome as in decoration, not the Chrome browser
	 */
	public class GeoWebChromeClient extends WebChromeClient {
		@Override
		public void onGeolocationPermissionsShowPrompt(String origin,
				GeolocationPermissions.Callback callback) {
			// Always grant permission since the app itself requires location
			// permission and the user has therefore already granted it
			callback.invoke(origin, true, false);
		}
	}

	WebView mWebView;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		mWebView = (WebView) findViewById(R.id.webView1);
		// Brower niceties -- pinch / zoom, follow links in place
		mWebView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
		mWebView.getSettings().setBuiltInZoomControls(true);
		mWebView.setWebViewClient(new GeoWebViewClient());
		// Below required for geolocation
		mWebView.getSettings().setJavaScriptEnabled(true);
		mWebView.getSettings().setGeolocationEnabled(true);
		mWebView.setWebChromeClient(new GeoWebChromeClient());
		// Load google.com
		mWebView.loadUrl("http://www.google.com");
	}

	@Override
	public void onBackPressed() {
		// Pop the browser back stack or exit the activity
		if (mWebView.canGoBack()) {
			mWebView.goBack();
		}
		else {
			super.onBackPressed();
		}
	}
}

The onCreate() method obtains the WebView and enables Javascript and pinch/zoom. The last few lines before loading the URL google.com are the most important. In addition to calling setGeolocationEnabled(true), we configure the WebView by passing it two kinds of “clients”: a chrome client, which handles UI, or “chrome”, events (no relation to the browser bearing that name) for your WebView, and a basic client, which handles content-related events such as errors and form resubmission.

First, let’s look at the WebViewClient as implemented in the inner class GeoWebViewClient. It’s not strictly necessary for geolocation, but does something that almost all WebView apps do, which is to load any new URLs (such as when the user touches a hyperlink) in the same WebView. The default behavior is to fire an Intent to load in another browser, which is rarely what you want.

Next, a WebChromeClient as implemented in GeoWebChromeClient is essential for geolocation to work in the WebView. Whenever the WebView encounters Javascript using the Geolocation API, the WebView calls the method onGeolocationPermissionsShowPrompt() in its associated WebChromeClient. The name of the method is slightly misleading in this context, as neither the WebView nor the WebChromeClient actually shows a prompt. If you want to show a prompt, this is the place to do it, and you can find an example in the AOSP source code for packages/apps/Browser/src/com/android/browser/Tab.java. Fortunately, since the app itself declares the ACCESS_FINE_LOCATION permission, the user has effectively already granted permission, and you can simply invoke the callback with the second argument (allow) == true.

The final touch on our app is to wire up the phone’s back button in the onBackPressed() method. If we can go back in the WebView, we do that; otherwise, we back out of the app altogether.

Thanks to Roman Nurik and several others on StackOverflow for your helpful past answers on this topic.

Posted in Android | Tagged: , , | Leave a Comment »

App Engine, Dart, and Android at DevNexus

Posted by David Chandler on March 23, 2012

DevNexus keynote

DevNexus keynote

First, a huge thank you to the volunteer organizers and sponsors of DevNexus! The Atlanta JUG‘s annual not-for-profit conference attracted 500 mostly Java developers this year and remains one of the best values of any developer conference in the world.

I gave an update on Google App Engine for Java (see slides) and a pitch for HTML5 + Dart (see slides).

There were a lot of talks on mobile / Web development this year, including:

  • JQuery Mobile framework (Raymond Camden, Adobe)
  • Intro to PhoneGap (Raymond Camden, Adobe)
  • Java-Powered Mobile Cross-Platform Mobile Apps with Phone Gap (Andrew Trice)
  • Web vs. Apps keynote (Ben Galbraith)
  • Easy Mobile Development: Intro to Appcelerator Titanium (Pratik Patel)
  • What’s New in Android (Robert Cooper)
  • Spring for Android (Roy Clarkson, Spring)
  • Mind-Blowing Apps with HTML5 Canvas (David Geary)

All the mobile / Web talks that I attended were standing room only (70-130 people, depending on room capacity). It seems that mobile in the enterprise is red hot and enterprise apps are good candidates for Web apps vs. native. I was particularly impressed with

Thanks again to Gunnar, Vince, Sudhir, and the gang for making DevNexus such a high-quality event.

Posted in Android, AppEngine, Dart | 6 Comments »

Is the mobile Web ready for business app developers?

Posted by David Chandler on March 15, 2012

Disclaimer: these thoughts are my own, not necessarily those of my employer.

I recently attended A Night with Sencha and Ted Patrick, and it got me thinking more about the mobile web. Mobile developers are clearly hungry for cross-platform solutions like Sencha and Titanium, and HTML5 promises significant cross-platform compatibility. (Action game developers, you can stop reading now because you already know that the high-performance mobile Web is not there yet. In fact, many folks I talked to last week at GDC are not even using the Android SDK, but rather the Android Native Development Kit to port games from iOS in C.)

Having said that, the mobile web for business app developers is arguably the easiest way to develop mobile apps, period, even without the side benefit of cross-platform compatibility. Why?

  • Web development frameworks is a rich and mature space. There are dozens of well-established popular frameworks on both client and server for MVC, CSS, JSON, etc. We’ve been doing Web development for almost 20 years now.
  • Web design tools abound. Although IDEs for native apps offer design & layout functionality, more designers are familiar with tools like Dreamweaver for HMTL+CSS. Firebug and Chrome DevTools are the ultimate WYSIWYG editors. Who wants to learn another style language when you’ve finally conquered CSS (kicking and screaming)?
  • Mobile browsers, like their desktop cousins, offer great tools for design and debugging (such as Safari Web Inspector and remote debugging with Chrome Beta for Android). Tools like the Window Resizer Chrome extension let you quickly test your app in a variety of different resolutions.
  • Frameworks like Sencha do a lot of the heavy lifting around RPC, local storage, dynamic UI creation & data binding. These things take a lot of work to do correctly in a native app.
  • You don’t have to worry as much about device compatibility. Mobile browsers aren’t perfect and there are still compatibility gaps (see mobilehtml5.org), but most players in the ecosystem are motivated to ensure that the browser runs well on all devices. The ecosystem is probably less concerned with your apartment finder app. Provided you’re using standard browser features, the browser vendor bears much of the testing burden.

So why does anyone write native apps?

  • Monetization, of course. But you can wrap your app in a WebView. As far as I know, WebViews aren’t an issue in any of the app markets with the possible exception of Apple, and according to Ted Patrick, Apple has been good about letting WebView apps in “once they get to know you and find that your app is reliable.” YMMV.
  • Native look and feel. Sencha / jqTouch does a convincing job with this on iOS. I haven’t seen it on Android.
  • Performance. I already mentioned this with respect to fast-moving games, but most business apps don’t use Canvas or a lot of CSS transitions. And with care, even large apps that manage a lot of data (like mobile GMail for the Web) can be snappy.
  • Hardware access. With HTML5, you can get the user’s location and even the accelerometer, but not the camera. At least not yet. But for most business apps, location is all you need.
  • Integration with the OS. If your app needs a ContentProvider or background Service or handles Intents, then you do indeed need a native app. Several well-known apps are succeeding with a hybrid approach, however, by using WebViews for rendering and native Services for data access. This simplifies the UI design as noted earlier while retaining other advantages of the platform.
  • Finally, native apps let you write code in something other than Javascript. Of course, you could try GWT or Dart and compile to JS, too. Ironically, many of the native cross-platform solutions also require you to write your app in Javascript.

Over the next few weeks, I’ll be porting my listwidget app to native Android and mobile Web using a variety of technologies. I’ll keep you posted.

Posted in Android, Dart, Google Web Toolkit | Tagged: , | 1 Comment »

Getting Started with Android

Posted by David Chandler on February 7, 2012

Fibonacci Series for Android

I’ve recently joined the Android Developer Relations team at Google and am thus renaming this blog David Chandler’s Journal of Java Web and Mobile Development. Some of my favorite Google platforms are intersecting in new ways all the time (witness today’s announcement of Chrome Beta for Android ICS). Having done Web development for 18 years, I now turn my attention to mobile development, where I’m cautiously hopeful that HTML5 will make it easier in the long run to build cross-platform mobile apps.

As I started to ramp up on Android, my first thought was, “Why on earth did I ever wait so long to try this?” There’s something magical about connecting the USB cable to my phone and seeing my own work appear there. Perhaps it’s because I was an iPhone user for a few years and felt out of touch with my phone as a Java developer. At any rate, in no particular order, here are a few notes that I hope will be helpful to Android newbies like myself. If you’re an experienced Android developer, it will no doubt take me a while to catch up with you. Please feel free to post your favorite tips and tricks in the comments as we go along.

Getting Started with Android

To get started, I installed the Android Developer Tools plugin for Eclipse and started working through the tutorials on the Android Developer site. At first, I was trying too hard. To get started, you really don’t need to worry about adb or running “android” from the command line, as you can launch the AVD manager and SDK manager right from Eclipse. The tutorials are written to run apps using the emulator, but it’s easy and faster to use your actual phone:

  1. On your phone under Settings | Applications or Settings | Security, allow “Unknown sources.”
  2. On your phone under Settings | Development, enable “USB debugging.” It’s also useful to enable “Stay awake” so you don’t have to unlock the screen frequently.
  3. Plug in your phone via USB cable and choose the “Mount as disk drive” option if prompted. You should now see it listed when you run “adb devices”.
  4. In Eclipse, click Debug as | Android Application. You will be prompted to choose a device (which should show up automatically) or launch an emulator. Edit the launch configuration for each project to change the default action.
That was easy.

Creating visual appeal

A visually appealing app is a strong indication of quality and is easier than you might think to create. Android Asset Studio is an online tool that will take any image or text, size it appropriately for various screen densities, and package it so you can just drop it into your res folder. Even easier, you can do it within Eclipse: choose File | New | Android icon set and just follow the prompts.

Capturing screen shots

When you upload your app in the Android Market, you’ll need two screen shots of your app. The ADT plugin for Eclipse has a tool that makes this easy. Open the DDMS perspective and click the camera tool to snapshot a running emulator or connected device.

There’s also a third-party utility to project your phone’s screen onto your display. This is really useful when giving Android talks for your local JUG or GTUG.

Packaging your app

When you’re ready to distribute your app, you’ll need to sign the .apk file. In Eclipse, choose File | Export | Android application and it will walk you through the process, including creating a keystore. To test your app on your phone, run “adb -d install path/to/your.apk” on the command line. The -d option selects connected devices. You can also use -e to target the emulator. You may get a warning that you need to uninstall the old version of your app first. If you do, just run “adb -d uninstall package_name,” where package_name is the root Java package associated with your app, like com.turbomanage.

Publishing to the Android Market

Go to the Android Market, sign up for an account, and upload your artifacts. Your app will be scanned for malware and should show up in an hour or two. It took me only a few days to get ramped up enough to create my first app, which I packaged and published in an afternoon. It really couldn’t be easier. When you publish, do pay attention to your application version and SDK version. Note that target SDK version is distinct from minimum SDK version, and both are important for maximum compatibility across devices.

Introducing Fibonacci Series for Android

For my first app, I took a shallow dip into my creativity pool and came up with a Fibonacci Series calculator. There are several Fibonacci apps (mostly involving stock trading) already, but I just needed a simple calculator for when I’m on a dinner date with friends and suddenly can’t remember one of the five-digit Fibonacci numbers, for example. Regular readers of this blog will recognize the related sunflower illustration thrown in for good measure. The app gave me a good opportunity to use simple TextViews, a custom view for the Canvas on which to draw the sunflower, and practice handling orientation changes (go ahead, turn it sideways and see what happens). Oh, and I incorporated a tabbed interface and the menu button also. There are lots of tutorials on these topics online already, so I think for now I’ll just point you to the source code.

As a newcomer from GWT, I found the concept of an Activity very familiar (GWT’s Activities and Places are deliberately modelled after the Android). I ran across only a few gotchas. One that I remember is that overriding onConfigurationChanged() in your Activity does not guarantee you will get notified of all orientation changes because it doesn’t get called if another app is in the foreground when the orientation changes. But no matter, you can check every time in the Activity’s onCreate() method. It also took me longer than it should have to figure out how to hook into the phone’s menu button (just override onCreateOptionsMenu()). The tutorials on the Android Developer site as well as the new Android Training section under Resources cover most of the beginner topics quite well.

For new developers, the single most useful page on the site is this one: Common Tasks.

And don’t forget the android tag on Stack Overflow, which Google officially supports.

Once again, here’s the source.

Enjoy!

Oh, and if you’re wondering about all the status bar icons in the screen shot above, yes, I really did publish the latest version to the Android Market while on the plane, listening to music, with USB cable connected. Android development is pretty addictive…

Posted in Android | 5 Comments »

 
Follow

Get every new post delivered to your Inbox.

Join 134 other followers