Sunday, October 20, 2013

Create custom button with round corner and shadow by XML

To create a button in Android app like this:


The layout XML:
<Button

    android:layout_width="match_parent"

    android:layout_height="80dip"

    android:background="@drawable/hi"

    android:text="@string/click_button"

    android:textColor="#999"

    android:textSize="18dip"

    android:textStyle="bold" />
The drawable file hi.xml:
<?xml version="1.0" encoding="utf-8"?>

    <layer-list xmlns:android="http://schemas.android.com/apk/res/android" >

    <!-- Bottom 2dp Shadow -->

    <item android:bottom="11px" android:top="19px" android:left="10px" android:right="10px">

        <shape android:shape="rectangle" >

            <solid android:color="#ccc" />

            <corners android:radius="7dp" />

        </shape>

    </item>

    <!-- White Top color -->

    <item android:bottom="15px" android:top="15px" android:left="10px" android:right="10px">

        <shape android:shape="rectangle" >

            <solid android:color="#FFFFFF" />

            <corners android:radius="7dp" />

        </shape>

    </item>

</layer-list>

Wednesday, October 16, 2013

Convert hex string to color in Android

I got a hex string from resource file, looks like this "#FF00BB00". I wanna to use it as a view's background color. In Java there is a function Color.decode(String), while it is not existed on Android.

But after read the android.graphics.Color of Android quickly there is a same and useful function Color.parseColor(String), just be careful the string shall format to "#FF123456" or "#123456".

Here is the code:
imageView.setBackgroundColor(Color.parseColor("#FF00BB00"));

Parser XML via XmlPullParser in Android app

It's easy and simple to use XmlPullParser in Android app, the key method is next(). Call next() to go to next tag in XML, then adjust the current position by the event type. Just notice there is a TEXT event with empty value between two lines.

Here is how to parser a asset XML file:

            InputStream is = getAssets().open("colors.xml");
            XmlPullParser parser = Xml.newPullParser();
            parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
            parser.setInput(is, null);
            int eventType = parser.getEventType();
          
            while (eventType != XmlPullParser.END_DOCUMENT) {
                if (eventType == XmlPullParser.START_DOCUMENT) {
                    System.out.println("Start document");
                } else if (eventType == XmlPullParser.START_TAG) {
                    System.out.println("Start tag " + parser.getName());
                } else if (eventType == XmlPullParser.END_TAG) {
                    System.out.println("End tag " + parser.getName());
                } else if (eventType == XmlPullParser.TEXT) {
                    System.out.println("Text " + parser.getText());
                }
                eventType = parser.next();
            }
            System.out.println("End document");
            is.close();


Tuesday, October 15, 2013

How to open Assets files of Android app

The key class is AssetManager, use Context:getAssets() to get the AssetManager object.

To open a file:
InputStream is = context.getAssets().open("foo");


To open a binary XML file. Be notice the XML files under assets folder will not be complied into binary file, so you have to use AssetManager.open() for them.
XMLResourceParser parser = myContext.getAssets().openXmlResourceParser("xml");


And also can list all the asset files:
String[] list = myContext.getAssets().open("sample/foo");

Monday, October 14, 2013

Automatica UI testing via UiAutomation for Android app

Google released a UI testing framework named UiAutomator in Android 4.1. Basically it provides functions to enumerate the currently forground activity UI hierarchy to get all the view items. Different with Monkey Runner, UIAutomator is not coordinate based, you can get the view item by it's label text or class name, and so on.

The UiAutomator is based on JUnit3. That means it is NOT a Android project, you can write the test case in Java but not Android Java, and get the jar file as the compiling result. The sample and introduction can be found on Android develop site here.

Except writing test case part(which take mostly effort actually), to get the UiAutomator run you need below steps:

1. Have JDK and ANT installed.

2. Create a Java project, NOT Android, in Eclipse.

3. In Properties > Java Build Path, select "Add Library > JUnit" to add JUnit3 lib, and select Add External JARs… ”to add android.jar and uiautomator.jar which located in android SDK folder.

4. Create the test case class, just use this file as mock up now. Let's say your project name is TestUI, it located at c:\workspace\TestUI, package name is com.testui, and you have the class as com.testui.LaunchSettings

5. In terminal, execute this command to get a build.xml:
        $android create uitest-project -n <project-name> -t 1 -p <project-path>
   so your command looks like this:
        $android create uitest-project -n TestUI -t 1 -p c:\workspace\TestUI

6. Execute this command to build the project:
        $ant build
   Watch the output to make sure the compiling is succeed.

7. Push the jar file into phone:
         $adb push bin\TestUI.jar /data/local/tmp

8. Run the test case:
          $adb shell uiautomator runtest TestUI.jar -c com.testui.LaunchSettings

Here we are all set.

How to trigger bug report programmically on Android device

There is a menu "Take a bug report" in developer option in Settings, and I am wondering whether there is a way to trigger the bug report in my app, here is what I found:

in code:
SystemProperties.set("ctl.start", "bugreport");

via adb:
adb shell setprop ctl.start bugreport

Android system defined colors

As you know there are already some defined colors in android.R.drawable, like dialog_holo_dark_frame or dialog_holo_light_frame. We can find them in Android SDK reference documents. But, you can not find the color value of the definitions and obviously the document does not list all the system colors.

I searched the AOSP soruce code then got the color list in framework, here it is (I love github, more beautiful than Google code site ^_^):
https://github.com/android/platform_frameworks_base/blob/master/core/res/res/values/colors.xml

You can find all the color definitions used in AOSP, with values. The only problem is lacking the indicator what the color looks like.

I spent a while to search an existed tool for that but failed. Maybe I can write one later. It will be simple, just list all the system color values with a visible indicator so you can easily pick up one.

Update at 10.20:
Wrote a simple app to list the colors:
https://play.google.com/store/apps/details?id=com.droidrise.systemcolors





Sunday, October 13, 2013

Use Google Drive service accounts for store application-owned data

I wrote an app to backup user files from Android phone SD card to Google Drive, with the user's Google account of cause, and I was just thinking about whether I can backup some application-owned data, like the configures, to a application-owned Google account. After some searching I found Google provides a special type named Google Drive service account for that.

Here is the description from Googel Drive SDK, looks easy and funny, I will check it out how to use it in a Android app.

Use service accounts as application-owned accounts

Service accounts are accounts associated with a service or a project. They do not belong to a user and can only be accessed programmatically by the associated application.
Just like regular user accounts, service accounts have access to Google Drive through the Google Drive API. This allows you to authenticate as the service account in order to manage a Drive that belongs to your project.

Why the screen flashes when adding a SurfaceView?

I tried to add a VideoView to a layout dynamic via code in my Android app, but the whole screen flashes when the VideoView was added first time. To make the problem simple, I changed the VideoView to SurfaceView, as VideoView extends SurfaceView, you know, but the issue was still there.

After all, I found out the Window was destroyed then re-created when the SurfaceView was adding, and the Window's pixel format was changed mean while, that guided me to the answer, the pixel format of the SurfaceView and the Activity was different so Window Manager forced the re-created.

To resolve it, just added online in Activity:onCreate() to set pixel format, as below:

getWindow().setFormat(PixelFormat.TRANSLUCENT);

Hello, Google Drive on Android

Last week I got a task to do a quick prototype with Google Drive SDK on Android device, to upload the files for Android phone to the Google Drive. After a week coding the app is done and basically looks fine. It was funny.

Thrift fails on Windows - thrift failed error: The command line is too long.

Meet a thrift compiling failure on my project on Windows 7. Using Maven in IntelliJ so I choiced maven-thrift-pluging for thrift files. For ...