Wednesday 31 August 2011

Android: referencing a custom view in an xml layout description

So you've created your own custom view called MyCustomView in a package named com.myproject.myviews, your custom view extends the View class (or one of its sub-classes) and it only has one constructor as follows:

public MyCustomView(Context context) {
 super(context);
 initialise();
}

Your custom view calls an initialise() method which you've defined to do all its initialisation. Next, you add this view to an xml layout definition as follows:

<view
  class="com.myproject.myviews.MyCustomView"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content" />

Now, when you run your app, it will crash failing to initialise the view. What you need to do to get over this is to add the following two constructors to your custom view:

public MyCustomView(Context context, AttributeSet attrs) {
  super(context, attrs);
  initialise();
}

public MyCustomView(Context context, AttributeSet attrs, int defStyle) {
  super(context, attrs, defStyle);
  initialise();
}

These two constructors call the super constructors required for inflating a view from xml.

Thursday 25 August 2011

Android: set ImageView image content from a url

Turns out the following code doesn't set the image content of an ImageView:

Uri myImageUri = Uri.parse(myImageAddress);
myImageView.setImageURI(imageUri);

If you inspect the LogCat log, you'll see a message something like "resolveUri failed on bad bitmap uri". Here's what you need to do instead...

URL myUrl = new URL(myImageAddress);
InputStream inputStream = (InputStream)myUrl.getContent();
Drawable drawable = Drawable.createFromStream(inputStream, null);
myImageView.setImageDrawable(drawable);

That should work once you've wrapped the necessary try/catch statements around it and set the "internet" uses-permission in the AndroidManifest file of course.

Wednesday 24 August 2011

Android: change colour of button

Ideally, to change the colour of a button whilst keeping the rest of the look and feel of the button the same, one would think that defining a style as follows and setting this to be the style of our button would do the trick:

<style name="button" parent="@android:style/Widget.Button">
 <item name="android:layout_width">wrap_content</item>
 <item name="android:layout_height">wrap_content</item>
 <item name="android:background">@color/mycolor</item>
</style>

Unfortunately, this doesn't have the desired effect. By doing the above (i.e. setting the background property to be a colour), you'll see that your button has lost its look and feel, and is now a plain rectangle with sharp (non-rounded) corners (though it does now have the colour specified). What you need to do instead is add an xml file (let's call it mycustombutton.xml) to your res/drawable folder, which defines the shape (colour etc) of your button for the different states it might find itself in (pressed etc), as follows:

<?xml version="1.0" encoding="utf-8"?>
<selector
 xmlns:android="http://schemas.android.com/apk/res/android">
 <item android:state_pressed="true" >
  <shape android:shape="rectangle" >
   <solid android:color="@color/mypressedcolor" />
   <corners android:radius="3dp" />
   <padding
    android:left="5dp"
    android:top="5dp"
    android:right="5dp"
    android:bottom="5dp" />
  </shape>
 </item>
 <item>
  <shape android:shape="rectangle" >
   <solid android:color="@color/mydefaultcolor" />
   <corners android:radius="3dp" />
   <padding
    android:left="5dp"
    android:top="5dp"
    android:right="5dp"
    android:bottom="5dp" />
  </shape>
 </item>
</selector>

The above specifies a curved rectangle with padding and colours for two different states (pressed and default). All that remains now is to set the background property of your button to have the value @drawable/mycustombutton.

Tuesday 23 August 2011

Android: Make a custom view class based on your own xml layout

Here's how to make your own custom view class which extends FrameLayout and which is based on an xml layout description saved in res/layout/mycustomview.xml and defined as follows:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="horizontal"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content" >
<TextView
  android:id="@+id/lblOne"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content" />
<TextView
  android:id="@+id/lblTwo"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content" />
</LinearLayout>

The above layout is a simple LinearLayout object containing two TextView objects. We define our custom view class based on this layout as follows:

public class MyCustomView extends FrameLayout {

  TextView lblOne;
  TextView lblTwo;

  public MyCustomView(Context context, String lblOneText, String lblTwoText) {
    super(context);
    LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View view = inflater.inflate(R.layout.mycustomview, null);
    addView(view);
    lblOne = (TextView) view.findViewById(R.id.lblOne);
    lblTwo = (TextView) view.findViewById(R.id.lblTwo);
    lblOne.setText(lblOneText);
    lblTwo.setText(lblTwoText); 
  }
}

This does nothing more than setting the text of the two of TextView objects but hopefully demonstrates the general idea!

See the following link for a demonstration of how to reference a custom view class in an xml layout description:

http://adilatwork.blogspot.com/2011/08/android-reference-custom-view-in-xml.html

Wednesday 17 August 2011

Getting started with the Android Facebook SDK

First thing to do is to link the Android Facebook SDK to your Android project.

Next, reference a Facebook object somewhere in your Android project code and add a method to initialise it with your Facebok app id. For example:

private static Facebook facebook;
public static void initialise(String facebookAppId) { facebook = new Facebook(facebookAppId); }

Before you can get or post any data from Facebook, you will need to initialise your Facebook object instance (using the method above for example) and then call one of the Facebook class authorize(...) methods for your app to be granted permissions to make Facebook api calls. For example:

facebook.authorize(MyActivity.this, new String[] { "publish_stream" }, new Facebook.DialogListener() { /* add implementation of DialogListener interface methods */ });

Once permissions are granted (i.e. authorisation is successful), you can start making requests to the Facebook api using the AsyncFacebookRunner class. For example, to get details of the current user, do the following:

new AsyncFacebookRunner(facebook).request("me", new AsyncFacebookRunner.RequestListener() { /* add implementation of RequestListener interface methods */ }

Or, similarly, to post a message to the current user's wall, do the following, where you can find an example of how to set up bundleParams in the comments below:

new AsyncFacebookRunner(facebook).request("me/feed", bundleParams, "POST", new AsyncFacebookRunner.RequestListener() { /* add implementation of RequestListener interface methods */  }, new Object());

Lastly, to log out the currently signed in user from Facebook, call the Facebook class logout(Context) method, passing the Context that was used to do the login (authorisation). For example:

facebook.logout(MyActivity.this);

That's it! That's the basics of using the Android Facebook SDK.

Thursday 11 August 2011

Android: handling gestures

The basics of detecting and handling gestures is a three step process follows:
(1) Add a GestureDetector instance to your Activity or View (as appropriate), e.g.

private GestureDetector gestureDetector;

(2) Instantiate it somewhere, the Activity's onCreate(...) method perhaps:

gestureDetector = new GestureDetector(MyActivity.this, new SimpleOnGestureListener()
{
@Override
public boolean onDown(MotionEvent e)
{
 return true;
}

 @Override
 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
 { /* do something */ }
});

(3) Override the Activity's onTouchEvent(...) method:

@Override
public boolean onTouchEvent(MotionEvent event)
{
 if (gestureDetector != null) return gestureDetector.onTouchEvent(event);
 else return super.onTouchEvent(event);
}

That's it. That's the basics. See comments for some extra niceties.

Android SQLite Database

The best (most simple and easy to follow) tutorial/guide for working with the Android SQLite database I could fine was this one:
http://www.vogella.de/articles/AndroidSQLite/article.html

Key points:
  1. Write a 'helper' class which extends SQLiteOpenHelper and manages database creation, upgrading, opening and so on.
  2. Write an 'adapter' class which references the 'helper' class and provides methods for opening and closing the database, as well as inserting records, fetching records and so on.
  3. Reference the 'adapter' class in your Activity classes to perform actions on the database.