Sunday, March 20, 2011

Including QR-reader in your app

Thanks to android intents, it is easy to include functionality from other apps to you own. Say for example you have an app that should be able to read QR-codes. You could easily call a barcode scanner to do the dirty work for you and just bother about the result.

Create a button that will launch Barcode Scanner from Zxing:
public Button.OnClickListener mScan = new Button.OnClickListener() {
    public void onClick(View v) {
        Intent intent = new Intent("com.google.zxing.client.android.SCAN");
        intent.setPackage("com.google.zxing.client.android");
        intent.putExtra("SCAN_MODE", "QR_CODE_MODE");
        startActivityForResult(intent, 0);
    }
};

Handle the callback for result:
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
    if (requestCode == 0) {
        if (resultCode == RESULT_OK) {
            String contents = intent.getStringExtra("SCAN_RESULT");
            String format = intent.getStringExtra("SCAN_RESULT_FORMAT");
            // Handle successful scan
        } else if (resultCode == RESULT_CANCELED) {
            // Handle cancel
        }
    }
}

This is a raw copy/paste from the ZXING-project. Nothing that I can take credit for, but I have tested it and it works as a charm.

Yes, it requires the user to have the Barcode Scanner installed. This can be handled smoothly by calling url instead - if the barcoder is installed - it will launch - otherwise launch a web browser (with a install guide of course). Very nice!

Wednesday, March 16, 2011

Extract HTML from Android webview

Having a webview in android and wanting to fiddle with the HTML?

Injecting javascript in android webview

Its easy, make sure you have javascript enabled and simply load url containing javascript:
mBrowser = new WebView(context);
mBrowser.getSettings().setJavaScriptEnabled(true);
mBrowser.loadUrl("javascript:getElementById('ad_container').style.display='none');");

In most cases, you first want to load the actual web page, then inject the javascript - this is done by using a WebViewClient which overrides onPageFinished.

mBrowser.setWebViewClient(new WebViewClient() {
   @Override
   public void onPageFinished(WebView view, String url) {
      // check url
      if (SOME_WEBPAGE.equals(url) {
        loadUrl(JAVASCRIPT_CODE);
      }
   }
});
mBrowser.loadUrl(SOME_WEBPAGE);

Extracting HTML from Android webview

Taking it one step further - let's get HTML from a page and use it in our program. This is accomplished by using a JavascriptInterface with our webview.

mBrowser.getSettings().setJavaScriptEnabled();
// add javascript interface with example method
mBrowser.addJavaScriptInterface(new JavaScriptInterface() {
   public void setTitle(String html) {
      mTitle = html;
   }
}, "MY_JS");
// add webview client that calls javascript interface when page is loaded
mBrowser.addWebViewClient(new WebViewClient() {
   @Override
   public void onPageFinished(WebView view, String url) {
       view.loadUrl("javascript:window.MY_JS.setTitle(document.getElementsByTagName('title')[0].innerHTML);");
   }

mBrowser.loadUrl(SOME_WEBPAGE);

That's it - using the combination of WebVievClient and JavascriptInterface is very powerful - drawback is that I have not found an easy way of debugging javascript - if your javascript fails it will fail silent.

Nice thing is you can test your javascript on Firefox using Firebug on your main computer before adding code to your android project.

Saturday, March 12, 2011

TravAlert Lite 1.1.1 released

TravAlert Lite has been updated.
It's a minor update but I hope you will enjoy the new features.

Account Editor
The Account Editor will no longer accept empty username or password and it will also validate the server to at least somewhat correct.

Notification settings
If you go to settings you will see that the notifications has got its own preference screen and you can now set ring tone/vibration separately for incoming attacks, no incoming attacks and error-notifications.

Wednesday, March 9, 2011

QR-code to launch your app

Android intents are powerful, you can even set you application to launch on a certain URL.

Launch app on defined URL

To make your app launch on a specific URL you simply create an intent filter.

<intent-filter>
  <action android:name="android.intent.action.VIEW"/>
  <category android:name="android.intent.category.DEFAULT"/>
  <category android:name="android.intent.category.BROWSABLE"/>
  <data android:scheme="http" android:host="xebralabs.blogspot.com" android:path="/travalert"/>
</intent-filter>

This way you can have your application launched from a QR-code containing the specific URL. Nice thing is that if the app isn't installed the user will most likely have the url opened in a browser instead.

Monday, March 7, 2011

Static buttons in listview

A common gui-layout strategy is having static buttons above or below a listview.

Consider the following layout:


This is accomplished by using a relative layout which includes the listview inside LinearLayout with bottom padding, then the buttons relative to parent.

Example layout xml of static buttons below listview. Key parameters are highlighted.
<RelativeLayout 
 android:layout_width="fill_parent"
 android:layout_height="fill_parent">

   <LinearLayout
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
     android:layout_alignParentTop="true"
     android:paddingBottom="50sp">

      <ListView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"/>

      <TextView
        android:id="@android:id/empty"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

   </LinearLayout>

   <Button
     android:layout_height="wrap_content"
     android:layout_width="124sp"
     android:layout_alignParentBottom="true"
     android:layout_alignParentLeft="true"/>

   <Button
     android:layout_width="124sp"
     android:layout_height="wrap_content"
     android:layout_alignParentBottom="true"
     android:layout_centerHorizontal="true"/>

   <Button
     android:layout_width="124sp"
     android:layout_height="wrap_content"
     android:layout_alignParentBottom="true"
     android:layout_alignParentRight="true"/>

</RelativeLayout>

TravAlert Lite 1.1.0 with Travian 4 (T4) support

1.1.0

TravAlert Lite has gotten its first update and can now handle Travian 4 (T4) servers as well. It has also been localized to Swedish.

Sunday, March 6, 2011

Proguard - keeping onclick methods from layout xml

The ProGuard tool shrinks, optimizes, and obfuscates your code by removing unused code and renaming classes, fields, and methods with semantically obscure names.

When running Proguard on your jar-file it is important to configure it to keep click listeners that you use from your layout xml.
# keep methods accessed from xml/android:onClick
-keepclassmembers class *{
public void *(android.view.View);
~
More on Proguard.
More on click listeners from layout xml.
~

Wednesday, March 2, 2011

TravAlert Lite is published on android market

TravAlert Lite

TravAlert Lite just got published on the android market. It's free as in free beer and free of ads!