Android: EditText Login/Password : intercept ‘OK’ and ‘ENTER’ on a LoginForm

Quick tips on a Login Form in an Android App, to enhance user experience: intercept ‘Enter’ in a TextView or ‘OK’ in a Numeric-only TextView

My Login Form is with a Relative Layout. Note that the Password field is numeric-only.

<EditText
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/start_userid"
    android:hint="@string/start_userid"
    android:layout_alignParentTop="true"
    android:layout_marginTop="50dp"
    android:layout_centerHorizontal="true"
    />
<EditText
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:inputType="numberPassword"
 android:ems="10"
 android:id="@+id/start_passwd"
 android:hint="@string/start_password"
 android:layout_below="@+id/start_userid"
 android:layout_centerHorizontal="true"
 />

The code to intercept “Enter” Key in UserId field, and “OK” in numeric-only Password field is:

mUserId = (EditText) findViewById(R.id.start_userid);
mUserPassword = (EditText) findViewById(R.id.start_passwd);

mUserId.setOnEditorActionListener(
  new TextView.OnEditorActionListener() {
    @Override
    public boolean onEditorAction(TextView textView, int actionId, KeyEvent keyEvent) {
        if (actionId == EditorInfo.IME_NULL && 
             keyEvent.getAction() == KeyEvent.ACTION_DOWN) {
            mUserPassword.requestFocus();
        }
        return true;
    }
});

mUserPassword.setOnEditorActionListener(
  new TextView.OnEditorActionListener() {
    @Override
    public boolean onEditorAction(TextView textView, int actionId, KeyEvent keyEvent) {
        if (actionId == EditorInfo.IME_ACTION_DONE) {
            doLogin(); // check login & so on
        }
        return true;
    }
});

Setup Apache Cordova in OSX Yosemite for Android & iOS apps

To use Apache Cordova on OSX Yosemite, the prerequisites are:

  • brew
  • npm

I assume both are available. In this quick blog, I will assume you’d like to compile, build and emulate your app for Android and iOs. Please remember that Cordova is also available for Window Phone 8, Firefox OS, … See Apache Cordova HomePage for details.

  1. Install ant using brew
    sudo brew update
    sudo brew install ant
    
  2. Check ant version:
    ant -version
  3. Install Cordova using npm
    sudo npm install -g cordova
    
  4. if you plan to compile cordova app for android, set ANDROID_HOME to point to Android SDK
    export ANDROID_HOME=~/android/sdk/
  5. If you plan to compile cordova app for iOS, install XCode from Apple Store
    https://itunes.apple.com/en/app/xcode/id497799835

    Then, you will need iOS Simulator from PhoneGap to test your app into iOS emulator:

    sudo npm install -g ios-sim
    

To make a small test project on OSX, please read Apache Cordova Starting Guide.

[To be continued]

Android : extract list of used drawables

Sometimes, I need to know which drawables are used in an Android project, and then remove unused. It happens as my project template contains the whole set of icons.

The first steps are to get a list of drawables declared in java classes and xml resources files. A bunch of find/egrep does it quickly:

1. Extract drawable names from resources files

find . -name '*xml' -exec egrep -oh "(@drawable/[a-z0-9_]{1,})" {} \; | awk -F/ '{print $2}'

2. Extract drawable names from java files

find . -name '*java' -exec egrep -oh "(R.drawable.[a-z0-9_]{1,})" {} \; | awk -F. '{print $3}'

Android : Start a Phone Call with Android API


For your app, you could need to start a phone call from it. Android API offers two methods (at least) to achieve that.

The first approach doesn’t require any specific permission but, it doesn’t really start the call. Instead, it displays the number to call to the user which could start it or not.

    Intent intent = new Intent(Intent.ACTION_DIAL);
    intent.setData(Uri.fromParts("tel", phoneNumber, null));
    startActivity(intent);

When you want to prepend the phone number with some special chars sequence (here with #31# prefix)

    Intent intent = new Intent(Intent.ACTION_DIAL);
    intent.setData(Uri.fromParts("tel", "#31# + phoneNumber, null));
    startActivity(intent);

The 2nd method is straitful : the call starts, but your app requires permission

    Intent intent = new Intent(Intent.ACTION_CALL);
    intent.setData(Uri.fromParts("tel", phoneNumber, null));
    startActivity(intent);

and do not forget to add the permissin in the manisfest:

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

For practical use, the 1st way is the right one as NO permission is required, so it’s a little bit less intrusive and less dangerous (for user’s billing).

Android : Memo, Tips and Tricks


This post is just a memo, kind of PasteBin.

Load data (bytes or string) for a file into Resources (raw directory)

    /**
     * Load a binary file from Resources
     *
     * @param context Context
     * @param resId   Resource to load
     * @return File content (byte[]), null if a failure occurs
     */
    public static byte[] loadResRawFile(Context context, int resId) {
        try {
            AssetFileDescriptor afd = context.getResources().openRawResourceFd(resId);
            long length = afd.getLength();
            InputStream is = afd.createInputStream();
            byte[] buffer = new byte[(int) length];
            is.read(buffer);
            return buffer;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Load a String file from Resources
     *
     * @param ctx   Context
     * @param resId Resource to load
     * @return File content (String), null if a failure occurs
     */
    public static String loadResStringFile(Context ctx, int resId) {
        try {
            return new String(loadResRawFile(ctx, resId));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }