Monday, 16 June 2014

Jekins and Android - Dependencies between jobs

If several code of the same project are stored in different repositories, such as the case of libraries, several jobs must be created since each job can only retrieve the code from on repository. In this case, there is a special way to execute the jobs related.

I am going to use an example to show this. Let's say we have a project called Main in the repository 1. This project depends on a library called library1 stored in the repository 2.

1. Configure the project.
In the project.profile of the project Main, it must have a relative path to the library1 directory IN JENKINS, not in the local computer. This could be the content:

android.library.reference.1=../../Library1/workspace

where "Library1" is the name of the job which is related with library1 configured in Jenkins.

Note that there are two levels "up"s. The first one is because the actual directory is in the folder workspace inside of the actual job, the second one is used to go back to the job level, where all the jobs have their own folder.

Once there, it goes to the job "Library1" and inside that folder, the folder workspace, where the data of the last stable compilations goes.

Now commit (and push) the changes to the repository.

2. Download this plugin for Jenkins, which is used to execute one project after another:
https://wiki.jenkins-ci.org/display/JENKINS/Build+Flow+Plugin

3. Creates a new project of build flow
3.1 On the home screen of Jenkins, click on new job
3.2 Enter the name of the job. Select the type of job as "Build Flow"
3.3 In the config of the project, under "Execution trigger", there will be a special windows called "Define build flow using flow DSL". Enter the follow lines

build("Main")
build("Library1")

Where Main is the name of the job in Jenkins which is related with the project Main.

Source:
StackOverFlow - Ant Build Android Project with Dependencies

Monday, 26 May 2014

Android - Hide and show textView

In android, when a text is quite big, it could be hidden and when you click on it, show the text.

1. Hide
To hide the text, the easier way is by using the attribute MaxLines and ellipsize to the end.
<TextView
    android:id="@+id/completeDescriptionTextView"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:maxLines="3"
    android:ellipsize="end"
/>

2. Show
Once the text has been hidden, if by any action of the user you wan to show the entire text, you should do the follow:

TextView completeDescriptionTextView = (TextView)findViewbyid(R.id.completeDescriptionTextView);
completeDescriptionTextView.setMaxLines(Integer.MAX_VALUE);
// The ellipsize must be set as null for android 2.3                                                          
completeDescriptionTextView.setEllipsize(null);
expandCompleteDescriptionTextView.setVisibility(View.GONE);
break;

3. Extra
In order to detect if the textview has been ellipsized, this works:
private boolean hasBeenEllipsized(TextView textView) {
    Layout layout = completeDescriptionTextView.getLayout();
    // If it contains layouts                                                                                                     
    if (layout != null) {
        int lines = layout.getLineCount();
        // Check if it contains text                                                                                                      
        if (lines > 0) {
            // Check if the last line has been elipsized                                                                                  
            if (layout.getEllipsisCount(lines-1) > 0)
                return true;
            }
        }
        return false;
    }
}

Source:
StackOverFlow - How to reset Android textview Maxlines
StackOverFlow - Check if textview is ellipsized in android

Wednesday, 21 May 2014

Action bar - Back to the home screen

In the action bar, native or ActionBar Sherlock, there are several way to create the up button and set it to come back to the previous screen. Here I have listed them.

Mainly there are two groups: natives and not natives. For each one of them, there could be static back and dynamic back

1. Native Back to home
For new version of Android, it comes with native action bar. It appears from Android 3.0.x HoneyComb (API 11). All the version of Android which is previous to HoneyComb cannot use the native ActionBar.

1.1 Dynamic Back to home
To add dynamically the back to home function, no extra manifest code need to be added. Instead, the java code should be used:

First of all, the home button must be called in the onCreate method

// Display the up button
getActionBar().setDisplayHomeAsUpEnabled(true);

Then, the code must override the method onOptionsItemSelected when the item id is android.R.id.home:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getItemId() == android.R.id.home) {
        // Back to the previous activity
       onBackPressed();
       return true;
    } else {
        return super.onOptionsItemSelected(item);
    }
}


Note I have used the notation @SuppressLint("NewApi") to avoid the error of new api because the min API of the example is 8, so the user cannot use this function on devices with API previous to 11, even when you can install this app on it.

1.2 Static Back to home
To create the static back to home the coder just have to add the follow code in the Android manifest file, following by the declaration of the activity.

            android:parentActivityName=""parentActivityName"

For example, if my activity is called "NativeStaticBackActivity" and the home activity is called "HomeActivity", this would be the code in the manifest.

<activity
    android:name="com.jiahaoliuliu.backtohome.NativeStaticBackActivity"
    android:label="@string/app_name"
    android:parentActivityName="com.jiahaoliuliu.backtohome.HomeActivity" ></activity>

Check this example for more information:

2. Not native Back to home
The problem about the native back to home is the minimum API required is 11. If you want your app to run on devices of previous versions, you must use an externa action bar.

For this example, I have used the ActionBarSherlock, a wonderful lib created by Jake Wharton, from Square.

2.1 Dynamic Back to home
The case of dynamic back to home is the same as the dynamic back to home for native action bar. First you should ask the action bar to show the up icon by adding the follow code into onCreate method:

// Display the up button
getActionBar().setDisplayHomeAsUpEnabled(true);

And then, override the method onOptionsItemSelected as follow:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getItemId() == android.R.id.home) {
        // Back to the previous activity
       onBackPressed();
       return true;
    } else {
        return super.onOptionsItemSelected(item);
    }
}

You can find an example here:

2.2 Static Back to home
In this case, both XML code in Android Manifest file and java code should be added.

2.2.1 Android manifest
The first thing to add is the same as the native action bar: The parent activity name.

android:parentActivityName="com.jiahaoliuliu.backtohome.HomeActivity" 

The second thing is a metadata before close the activity of where the parent is

<meta-data
    android:name="android.support.PARENT_ACTIVITY"
    android:value="com.jiahaoliuliu.backtohome.HomeActivity" />

2.2.2 Java code
First, the code must ask the action bar to show the up button for devices with API lower than 11:

// Display the up button
getSupportActionBar().setDisplayHomeAsUpEnabled(true);

Second, the method onOptionsItemSelected must be overridden again. Note that this time the code is using the method navigateUpFromSameTask of the class android.support.v4.app.NavUtils. This is what the android developer page states:

To navigate up when the user presses the app icon, you can use the NavUtils class's static method,navigateUpFromSameTask(). When you call this method, it finishes the current activity and starts (or resumes) the appropriate parent activity. If the target parent activity is in the task's back stack, it is brought forward as defined by FLAG_ACTIVITY_CLEAR_TOP.

@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
        NavUtils.navigateUpFromSameTask(this);
        return true;
    }
    return super.onOptionsItemSelected(item);
}

You can find an example here:
Manifest:

Activity

Conclusion:
The action bar has stablished as a pattern for mobile apps, such as Drawer or Sliding menus. It is very important to provide a clean up navigation to not confuse the user.

The use of static back to home method is good if from one activity it just goes to one specific activity. Other wise, if one activity is called by several different activities, it is better use the dynamic back to home method because it is impossible to do it with static back to home method.

Also the minimum API supported by the native action bar is 11, which means if you want to reach most of the people (at the time of writing there are still nearly 17% of the users who has a device with API lower than 11), an external library must be used. I have used ActionBarSherlock, but the new ActionBar compat could be used too.

You can find the example here:

For more information:

Tuesday, 6 May 2014

Git branches

The manage of branches in Git is might be the most powerful function of this Distribution revision control tool.

I am follow the recommendation of Nvie, which has the follow schema:

- There are two permanent branches, whom are "dev" and "master"
- The first thing to do with the new repository is create the "dev" branch from "master"
- To develop each function, a new branch from "dev" is created
- When a function has been finished, it is merged into the branch "dev". Here I use the option "--squash", which puts all the commits from the functional dev into one. This ensures the branch "dev" will not have middle commits from the function branches. whom could not be stable.
- When I consider that the branch "dev" has all the functions, I creates a new branch which is send to the tester.
- For each bug found by tester, a new branch will be created. Once the bug has been fixed, the new branch will be merged with the release branch. The release branch will be also merged with "dev" branch, to push the bug fix to the "dev" branch.
- When almost all the bugs has been fixed, the release branch will be merged with master branch to be released in production. A tag will be created.
- If after the product has been released a new bug has been found in the production environment, a new branch called "hotfix" will be created from "master" branch. After the bug has been fixed, the branch "hotfix" will be merged with the branch "master" and the branch "dev". A new version of the product with the bug fixed will be released in the market.

Source and more info:

Monday, 28 April 2014

Jenkins with Android - Saving the apk generated

After config Jenkins to compile and test Android project, it could be configured to save the apk file generated for each compilation.

1. Go to the configuration of the job and under "Post-build Actions", click on "Add post-build action"
2. Select "Archive the artifacts"
3. In the folder Files to archive, enter the path to the APK file. Usually it is under the folder bin and it is the name of the project and "-debug.apk".

For example, for the project "AutoCompleteTextViewHack", the apk is under "bin/AutoCompleteTextViewHack-debug.apk".

If you don't know which one is, compile the project and then, on the main page of the job click on "Workspace" and browser in the bin folder to find the apk you want to save.

Signing Android projects in Eclipse - Suddenly crash

Sometimes I found Eclipse suddenly crashes if I try to sign an Android project. The a new text document like the below appears:

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGBUS (0x7) at pc=0xb45a1713, pid=2780, tid=2105924416
#
# JRE version: Java(TM) SE Runtime Environment (7.0_55-b13) (build 1.7.0_55-b13)
# Java VM: Java HotSpot(TM) Client VM (24.55-b03 mixed mode linux-x86 )
# Problematic frame:
# C  [libzip.so+0x4713]  newEntry+0x73
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.sun.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#

The fact is this error appears sometimes and using the solution given above it still appears. This could be a good solution:

1. On the menu, Open Project and click on "Build Automatically" to uncheck it.
2. Clean the projects by clicking on Project -> Clean
3. Build manually your project (only your project, not any other libraries) by right click on your project and select Project -> Build project
4. Now try to export the signed version of your project by right click on your project and select Android Tools -> Export signed Application.

Source:

Thursday, 24 April 2014

Continue integration: Jenkins, git and Android

As I stated in early posts, Jenkins is an excellent tool for continue integration because it could be integrated with repositories (git, svn) and for each commit or push, it could starts compile automatically and do the tests. After it, the result could be send via email.

For Android, it could be more useful. It could be used to run 64 emulators, each one with different configurations, so for each unit tests it could run on 64 configurations. It also could be used to keep the apk generated, so for each compilation, it could send the apk file to a set of receivers by email, so they can have always the last version of project.

In this post I am going to summarize the steps needed for a simple configuration and link process with a github project.

1. Install plugins
To run the android projects, it is needed to install two more plugins, beside the one installed.
1.1 From the main windows of Jenkins, go to Manage Jenkins -> Manage plugins
1.2 Select Availables
1.3. Find the follow plugins and check the checkbox
- Android Emulator Plugin (Compulsory)
- Android Lint Plugin (Optional)
- Git Plugin
- Git client plugin (It comes with Git Plugin)
1.4 Click on the button "Download now and install after restart". Then wait until Jenkins has been restarted.

2. Set Jenkins
After the plugins have been installed, there are some configurations to do
2.1 From the main windows of Jenkins, go to Manage Jenkins -> Configure System
2.2 On Android, check "Automatically install Android components when required". This will download the sdk and the emulators needed for the compilation. It will also set the ANDROID_HOME environment for Jenkins.



3. Create a new job for Jenkins
3.1 From the main windows of Jenkins, click on New Items
3.2 Set the Job name
3.3 Select "Build a free-style software project"
3.4 Click on Ok.

4. Set the git repository
4.1 In "Source Code Management", select Git
4.2 Enter the repository url. For example, it could be:

4.3 On the branches to build, leave it to "*/master" or change to any branch you want

5. Set the Emulator
5.1 On the "Build Environment", check the "Run an Android emulator during build"
5.2 Select "Run emulator with properties"
5.3 Enter the data for the emulator. For example, here is what I have done:
Android OS version: android-19
Screen density: 160
Screen resolution: WXGA800
Device locale: en_US
SD card size: 128M
Target ABI: armeabi-v7a



5.3 Disable the "Show emulator window".
5.4 Disable "Use emulator snapshots". It seems that after reboot, the Android emulator plugin has some problem to restart the emulator from the snapshot. I hope it could be fixed soon.

6. Set the ant data
Apache ant could be used to build, install and test the projects. The bad news is you will need ant, Maven or Gradle to install and test your project in the emulator. The good news is Android SDK comes with an tool to generate the ant files automatically.
Check here to see the steps.
I have set the ant file (build.xml) for the project above, so for this example you don't have to do anything.
6.1 On Build, click on "Add build step" and select "Invoke Ant"
6.2 Click on "Advanced ..." and enter the follow data:
Ant Version: Default
Targets: debug
Build File: build.xml
Properties: sdk.dir=$ANDROID_HOME

6.3 Click on "Add build steps" and select "Invoke Ant" again.
6.4 Click on "Advanced ..." again and enter the follow data
Ant version: Default
Targets: installd
Build File: build.xml
Properties: sdk.dir=$ANDROID_HOME


Check here for more ant options for Android:
Android developers - Building and Running from the Command Line

7. Save the project
7.1 Save the project by click on "Save" button

8. Running the project
8.1 On the project view, click on "Build Now" on the left panel and Jenkins will start build the project
8.2 Click on the link of the project to see the build
8.3 Click on the "Console output" on the left panel to see the progress.
If everything went well, the result of the project will be success.

Source:
Z├╝hlke Blog - Configure your Android project on Jenkins
Vitor Baptista - Continuos Integration for Android Apps with Jenkins and Maven 3
Android developers - Managing Projects fromm the Command Line
Android developers - Building and Running from the Command Line
Jenkins Wiki - building an Android app and test project
Vogella - Continuos Integration with Jenkins - Tutorial