Tuesday, 27 December 2011

Android: Twitter login using twitter4j library

At the time of writing the best tutorial I could find for integrating Twitter into an Android app using the twitter4j library was this one...

http://blog.blundell-apps.com/sending-a-tweet/

... I set up Twitter user authentication as in the tutorial above such that the Activity doing the Twitter authentication has its content view changed to a WebView, the Activity is declared in the manifest file containing an intent-filter to catch the Twitter callback and, on callback, the response is processed and the Activity's content view is changed back to whatever it was.

I got it working but in doing so I found (what I think is) an easier way and such that the WebView doesn't ever kick off the phone's web browser app (thereby leaving your app, which you don't really want), as follows:

(1) Remove the Activity singleInstance and intent-filter declarations you added to the manifest file (in following the tutorial above). Don't need that anymore!

(2) Add a WebView to your Activity layout file and set its initial visibility to "gone" and its position, height, width etc however you want it. I set its properties so that it covers the whole screen when visible, as follows:

<WebView
  android:id="@+id/myWebView"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:visibility="gone" />

(3) Get a handle to your WebView in your Activity and set its WebViewClient to pick up the Twitter callback (and not to kick off the web browser app at any time), as follows...

myWebView = (WebView)findViewById(R.id.myWebView);
myWebView.setWebViewClient(new WebViewClient()
{
  @Override
  public boolean shouldOverrideUrlLoading(WebView webView, String url)
  {
    if (url != null
        && url.startsWith("myapptwittercallback:///myapp"))
      handleTwitterCallback(url);
    else
      webView.loadUrl(url);
    return true;
  }
});

... Here you might also want to enable other settings of your WebView like saving form data and javascript execution (e.g. myWebView.getSettings().setJavaScriptEnabled(true);)

(4) Make your WebView visible and focused at the point you need to do Twitter authentication, as follows:

try
{
  twitter = new TwitterFactory().getInstance();
  twitter.setOAuthConsumer(
      myTwitterConsumerKey,
      myTwitterConsumerSecret);
  twitterRequestToken = twitter.getOAuthRequestToken(
      "myapptwittercallback:///myapp");
  myWebView.loadUrl(
      twitterRequestToken.getAuthenticationURL());
  myWebView.setVisibility(View.VISIBLE);
  myWebView.requestFocus(View.FOCUS_DOWN);
}
catch (TwitterException ex)
{
  Toast.makeText(
      this,
      "Login failed. Please try again.",
      Toast.LENGTH_SHORT).show();
}

... Remember to clear your WebView's history (i.e. myWebView.clearHistory() and set its visibility to "gone" in your handleTwitterCallback(String) method.

(5) Lastly, override your Activity's onBackPressed() method so that your WebView handles presses of the back button if its visible, as follows...

@Override
public void onBackPressed()
{
  if (myWebView.getVisibility() == View.VISIBLE)
  {
    if (myWebView.canGoBack())
    {
      myWebView.goBack();
      return;
    }
    else
    {
      myWebView.setVisibility(View.GONE);
      return;
    }
  }
  super.onBackPressed();
}

That's it! You should now have Twitter integration in your app and the user should never leave your app in doing Twitter authentication.

Saturday, 17 December 2011

Testing your Map and Location-aware app on the Android emulator

First of all, start up an emulator and get your app running on the emulator (from within Eclipse or however you do it). Sometimes the Android Debug Bridge (or maybe it's the Android Virtual Device manager that) gets its pants in a twist and it can't find the emulator you've started up. In this case you should run the following sequence of commands from the command prompt: 'adb kill-server'; 'adb start-server'; 'adb devices'; and then 'adb devices' again to be doubly sure you can see your emulator in the list of devices!

Next, with your app running on the emulator, start up the Dalvik Debug Monitor (by double-clicking the 'ddms' Windows batch file in the android-sdk 'tools' folder) and select your emulator (from the list of running emulators) as the one to feed data into. Select the 'Emulator Control' tab (still within the Dalvik Debug Monitor), scroll down to 'Location Controls', and with the 'Decimal' radio button selected (rather than the 'Sexagesimal' radio button), enter the Latitude and Longitude values to feed to your app (running on the emulator).

For London: enter Latitude as 51.5 and Longitude as -0.13.
For Belfast: enter Latitude as 54.6 and Longitude as -5.93.
And so on and so forth for various Latitude (north/south) and Longitude (east/west) values which you can find on websites like getlatlon.com.

Wednesday, 23 November 2011

HTC Wildfire S mobile network not working fix

Got my new phone (a HTC Wildfire S) a couple of weeks ago and whilst the WiFi internet was working fine, I was having problems connecting to the non-WiFi mobile (2G/3G) network. The fix took a bit of time to find so thought I'd share...

Go to 'Settings', then 'Wireless & networks', then tick the 'Mobile network' option, then click into the 'Mobile networks' options screen. From here, select your desired 'Network Mode' (I chose 'GSM / WCDMA auto'), go into the 'Network operators' screen and select your preferred network (I chose the 'Select automatically' option which found my network provider [Virgin]), and lastly... our antagonist... click into the 'Access Point Names' (APNs) screen...

If you find an Access Point Name here (in the APNs screen) corresponding to your network provider, select it. Otherwise, click the menu button, select the 'New APN' option, enter details of your access point (for me simply entering Name as Virgin and APN as goto.virginmobile.uk did the trick), save it and then select it in the APNs screen. If that doesn't work for you, try doing an online search for "android access point name" to see what the access point settings should be for your mobile network provider.

Monday, 7 November 2011

Android: emulating different screens

Putting this up for possible future personal reference. Here's three different emulator settings to test three different screen size/density combinations, as follows:

Low density: 120dpi; Skin: QVGA (320px*240px).
Medium density: 160dpi; Skin: HVGA (480px*320px).
High density: 240dpi; Skin: WGVA800 (800px*480px).

Note to self: the 'Q', 'H' and 'W' in QVGA etc stand for "Quarter", "Half-size" and "Wide" respectively, and VGA stands for "Video Graphics Array".

Thursday, 27 October 2011

Android: changing background color or drawable of a custom View when it's pressed or focused

Let's say you've created your own custom view named MyCustomView which extends the FrameLayout class and you've added to it your own xml layout (as defined in layout/mycustomview.xml), something like the following post:

http://adilatwork.blogspot.com/2011/08/android-make-custom-view-class-based-on.html

Now you want MyCustomView to change its background color or drawable when it's pressed or focused. The first thing you'll need to do is define a State List resource. This is done by creating an xml file in the res/drawable folder (let's called it res/drawable/mystatelist.xml) which has contents something like the following:

<?xml version="1.0" encoding="utf-8"?>
<selector
 xmlns:android="http://schemas.android.com/apk/res/android">
 <item
  android:state_pressed="true"
  android:drawable="@color/mypressedcolor" />
 <item
  android:state_focused="true"
  android:drawable="@drawable/myfocusedcolor" />
</selector>
We'll assume mypressedcolor and myfocusedcolor are colors defined in the res/values folder. The values of android:drawable of course needn't necessarily be a color but can alternatively be a drawable with value something like the following:

android:drawable="@drawable/mypresseddrawable"
Next, somewhere in MyCustomView we need to set its background resource to be the State List resource we just defined, and to also set MyCustomView to be focusable and clickable, as follows:

setBackgroundResource(R.drawable.mystatelist);
setClickable(true);
setFocusable(true);
Note that you're setting the properties (background resource, is focusable, is clickable) of MyCustomView itself and not the properties of the outermost node in the mycustomview.xml layout file which is added to MyCustomView (like I did mistakenly!).

That's it. You've defined a custom view and now it changes its background color or drawable when it is pressed or focused.

Tuesday, 25 October 2011

Android: taking a picture and then deleting it from external storage

I've been playing with the bulit-in camera app today, launching it from within my app, taking a picture and then returning back to my calling activity (let's call it MyActivity) with an Intent containing a Uri instance pointing to the saved picture. I used the following guide to do this...

http://developer.android.com/guide/topics/media/camera.html#intents

... but with one difference: I didn't specify where to save the file, saving the picture instead in the default picture gallery location. Getting to the point of this post... say the Intent returned in the MyActivity.onActivityResult(int, int, Intent) method is named data and I get the Uri pointing to the picture out from data as follows:

Uri myPictureLocation = data.getData();

... Then, if I want to delete the saved picture once I am done with it, the thing to bear in mind is that myPictureLocation is not a file location but data pointed to by a content provider. So, you don't delete the picture as follows (like I tried!!)...

File myFile = new File(myPictureLocation.getPath());
myFile.delete();

...but instead you would chain the following method calls...

MyActivity.this.getContentResolver().delete(myPictureLocation, null, null);

Friday, 14 October 2011

Android: parsing/formatting dates and currencies

I got back a date from an API call in the following format: "2008-03-29T00:00:00Z". To parse this String and get a Date instance, I created a SimpleDateFormat instance as follows...

SimpleDateFormat myDateTimeFormat = new SimpleDateFormat("yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'");

... and then parsed my String representation of a Date as follows...

String myDateString = "2008-03-29T00:00:00Z";
Date myDate = myDateTimeFormat .parse(myDateString);

... To get back the original String value from the Date instance I would call the format(...) method as follows...

myDateString = myDateTimeFormat .format(myDateString);

... In a similar fashion, if I wanted to format a number as a String showing the pounds sterling currency symbol and two decimal places, I could do something like the following...

double myNumber = 25;
DecimalFormat myCurrencyFormat = new DecimalFormat("£#.00");
String myFormattedNumber = myCurrencyFormat.format(myNumber);

... The value of myFormattedNumber in the above example would be "£25.00".

Both dates and currencies can be formatted smarter using pre-defined formats and locale information. The above is intended only as a quick guide to get you started parsing and formatting dates and currencies.

Android: creating an aynchronous task to make a http request

What we'll do to make an aynchronous http request is extend the AsyncTask class (overriding the doInBackground(...) and onPostExecute(...) methods) as follows...

public class MyAsyncTask extends AsyncTask<HttpRequestBase, Void, HttpResponse>
{
 @Override
 protected HttpResponse doInBackground(HttpRequestBase... httpRequests)
 {
  DefaultHttpClient httpClient = new DefaultHttpClient();
  HttpResponse response = httpClient.execute(httpRequests[0]);
  return response;
 }
 @Override
 protected void onPostExecute(HttpResponse httpResponse)
 {
  // handle response
 }
}

... and then instantiate the new MyAsyncTask class and call its execute(...) method passing in a HttpRequestBase instance as a parameter to make a http request. We could make this MyAsyncTask class smarter, constructing it with a DefaultHttpClient instance instead of creating a DefaultHttpClient instance in the doInBackground(...) method, or constructing the MyAsyncTask class additionally with a handler that reports back completion of the http request in the onPostExecute(...) method, or making changes to allow multiple simultaneous http requests to be dispatched. Hopefully though the above serves as a bare bones example to explain the general concept and to get you started.

Tuesday, 11 October 2011

Android: how to make a RESTful GET request using Http basic authentication

Let's assume we're sending a request to the url https://mytargetdomain.com/verify to verify a certain username and password combination, and we'll get a 200 status code on success. The code for this is as follows:

DefaultHttpClient httpClient = new DefaultHttpClient();
httpClient.getCredentialsProvider().setCredentials(
 new AuthScope(null, -1),
 new UsernamePasswordCredentials("myusername", "mypassword"));
HttpGet httpGet = new HttpGet("https://mytargetdomain.com/verify");
try
{
 HttpResponse response = httpClient.execute(httpGet);
 StatusLine statusLine = response.getStatusLine();
 int statusCode = statusLine.getStatusCode();
 if (statusCode == 200) { /* authorisation successful, do something... */ }
 else { /* authorisation failed, do something... */ }
}
catch (Exception ex) { /* Exception caught, do something... */ }
httpClient.getConnectionManager().shutdown();

Of course, this is a non-asynchronous call, which is not recommended, but hopefully this post serves the purpose of showing how to make a RESTful GET request using Http basic authentication.

Friday, 9 September 2011

GWT: creating a dialog prompt or popup panel

The class to use is DialogBox or PopupPanel and both are pretty straightforward to use. You just create an instance of DialogBox (or PopupPanel), make calls to the set methods you need (setTitle(,,,), setText(...), setAnimationEnabled(...), setGlassEnabled(...), addStyleName(...), setWidget(...) etc) and then call the DialogBox's show() or center() method to show it and the DialogBox's hide() method to hide it.

The only differences I see right now (I'm sure there are others) is that a DialogBox can be dragged around by the user and a PopupPanel on the other hand has an auto-hide property which could be handy.

Thursday, 1 September 2011

Android: methods for converting pixels to density-independent pixels, and vice versa

When creating Views or setting heights, widths, margins and so forth of Views programmatically (i.e. not in the xml layout files), the values to set are all in pixels, which is no good when you're trying to work with density-independent pixels (dips). So here's a couple of methods convert from pixels to dips and vice versa should the need arise:

/**
 * Converts the given number of pixels
 * to the corresponding number of density-independent pixels
 * using the formula: dip = px / (dpi / 160).
 */
public static float convertPxToDip(Context context, float pixels) {
 DisplayMetrics dm = context.getResources().getDisplayMetrics();
 return pixels / dm.density; // dm.density gives the scaling factor

 // alternative way of doing it
 // return (pixels * DisplayMetrics.DENSITY_DEFAULT) / (dm.densityDpi);
}

/**
 * Converts the given number of density-independent pixels
 * to the corresponding number of pixels
 * using the formula: px = dip * (dpi / 160).
 */
public static float convertDipToPx(Context context, float dip) {
 DisplayMetrics dm = context.getResources().getDisplayMetrics();
 return dip * dm.density; // dm.density gives the scaling factor

 // alternative way of doing it
 // return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, dm);
}

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.

Thursday, 28 July 2011

Android: how to use ColorStateList

(1) Create a folder in the 'res' folder and name it 'color'.

(2) Create an Android xml file in the new 'color' folder and name it 'mycolorlist.xml' or another name of your choosing. Place the following markup in your new xml file:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
 android:color="@color/mycolor1"
 android:state_pressed="false" />
<item
 android:color="@color/mycolor2"
 android:state_pressed="true" />
</selector>

Be sure that 'mycolor1' and 'mycolor2' are colours specified in your 'res/values/colors.xml' file. If you're not sure how to specify colors in your 'colors.xml' file, see the end of this post.

(3) Add the following code to the TextView to which you wish to apply the new ColorStateList...
myTextView.setTextColor(getResources().getColorStateList(R.color.mycolorlist));
... where myTextView is a TextView instance.

Done! Now when myTextView is pressed, its colour will be 'mycolor2', and otherwise its colour will be 'mycolor1'.

Lastly, here is an example of what your 'colors.xml' file might look like...
<?xml version="1.0" encoding="utf-8"?>
<resources>
 <color name="mycolor1">#ff005eff</color>
 <color name="mycolor2">#ff86C4ed</color>
</resources>
... which specifies two different shades of blue.

Android: underline text programmatically

It's as easy as putting the following code in your Activity class...
TextView myTextView = new TextView(this);
SpannableString mySpannableString = new SpannableString("My String");
mySpannableString.setSpan(new UnderlineSpan(), 0, mySpannableString.length(), 0);
myTextView.setText(mySpannableString);

Android: make text bold programmatically

It's as easy as this...
myTextView.setTypeface(null, Typeface.BOLD);
... where myTextView is your TextView instance.

Tuesday, 26 July 2011

GWT: how to make and show a PopupPanel

Code sample for creating and showing a simple popup in gwt which has some styling, is centred in the browser and which contains a single string and a single button to close/hide the popup:

final PopupPanel popup = new PopupPanel(false);
popup.addStyleName(Resources.instance.styles().popup());
Button btnClose = new Button("Close");
btnClose.addClickHandler(new ClickHandler()
{
 @Override
 public void onClick(ClickEvent event) { popup.hide(); }
});
FlowPanel fpPopupContents = new FlowPanel();
fpPopupContents.add(new Label("My message"));
fpPopupContents.add(btnClose);
popup.setWidget(fpPopupContents);
popup.center();

Android: how to make and show an AlertDialog

Found a fair few tutorials on how to make and show an AlertDialog but this one seems to be the easiest...

AlertDialog.Builder builder = new AlertDialog.Builder(myActivityContext);
builder.setCancelable(true);
builder.setTitle("My title");
builder.setMessage("My message");
builder.create().show();

The AlertDialog.Builder has lots of other options such as for adding buttons to the AlertDialog. See the Android Developers 'Creating Dialogs' page at the following link for more info on this and other general information about creating dialogs:
http://developer.android.com/guide/topics/ui/dialogs.html

Note: if it's just a text message you need to display to the user, consider using Toast.makeText(...).show() instead... though, however, a Toast message is only visible for a few seconds at most before it disappears so not exactly ideal if user input or confirmation is required before closing the popup.

Friday, 22 July 2011

Android: connecting to localhost

To connect the emulator to localhost, the urls...

"http://localhost:" + portNumber + "/" + subDirectoryName
"http://127.0.0.1:" + portNumber + "/" + subDirectoryName

... won't work. Use instead...

"http://10.0.2.2:" + portNumber + "/" + subDirectoryName


For more info on this, see the Android developer Using the Android Emulator page, Emulator Networking section:
http://developer.android.com/guide/developing/devices/emulator.html#networkaddresses

Android: aligning views in parent ViewGroup instance

It seems LinearLayout doesn't do anything with 'layout_alignParentRight' etc parameters though it does compile/build ok with these specified. So if you want to align a View within its parent ViewGroup instance, use RelativeLayout instead.


The downside of using RelativeLayout is that for each child View you have to remember to specify which other child View it is relative to and how (e.g. layout_toLeftOf, 'layout_below' etc ).

Android: how to make only part of a Textview string clickable

Say you have a string "Some text [clickable]" which you want to add to a TextView and you only want the "[clickable]" part of the string to be clickable. The way to go about it is to add the following code to your Activity class:

TextView myTextView = new TextView(this);
String myString = "Some text [clickable]";
int i1 = myString.indexOf("[");
int i2 = myString.indexOf("]");
myTextView.setMovementMethod(LinkMovementMethod.getInstance());
myTextView.setText(myString, BufferType.SPANNABLE);
Spannable mySpannable = (Spannable)myTextView.getText();
ClickableSpan myClickableSpan = new ClickableSpan()
{
 @Override
 public void onClick(View widget) { /* do something */ }
};
mySpannable.setSpan(myClickableSpan, i1, i2 + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

If you wanted the clickable part of your TextView to open up a url by means of a WebViewActivity, for example, you would put the following code in the ClickableSpan.onClick method:


Intent i = new Intent(MyActivity.this, WebViewActivity.class);
i.putExtra("url", getResources().getString(R.string.myurl));
startActivity(i);

Thursday, 21 July 2011

Android app internet access

In order for an Android app to be allowed access to the internet, it must specify a request for this permission in its manifest, as follows:
<uses-permission android:name="android.permission.INTERNET"></uses-permission>

Android: Referencing a library project

Just spent a frustrating hour(+) trying to figure out why my 'FlexStore' Android project couldn't find the classes of my 'KSD Android Utils' library project which was part of the same workspace. In the 'FlexStore' project Properties window, I had navigated to the 'Java Build Path' page and added the 'KSD Android Utils' project, and it was compiling fine. Turns out, what I had to do instead was navigate to the 'Android' page in the 'FlexStore' project Properties window and add the 'KSD Android Utils' library reference.


See the 'Managing Projects from Eclipse with ADT' android developers page for more info on this:
http://developer.android.com/guide/developing/projects/projects-eclipse.html

When Android debugger can't attach to the emulator...

If you select an app to debug from eclipse but instead of the app loading up on the emulator you get a message saying: "waiting for the debugger to attach"... best thing (I have found) to do is open up the windows command prompt, enter the command "adb kill-server", wait a second and then enter the command "adb devices". Your debugger at this point should attach to the emulator and your app should load up.

Tuesday, 19 July 2011

GWT: When the browser's scrollbars don't show...

... try adding the overflow:auto css property to your root view. For example,

(1) Define the .overflowAuto style in your styles.css file, as follows:
.overflowAuto { overflow:auto; }

(2) Declare it in your Styles.java file, as follows:
public String overflowAuto();

(3) Add it to your outermost HTMLPanel's styles in RootView.ui.xml, as follows:
<g:HTMLPanel addStyleNames="{res.styles.overflowAuto}">

That should work. The problem seems to arise when using LayoutPanels (and similar panels?) but haven't investigated it thoroughly so just an inkling.

Friday, 24 June 2011

Structure of an Android App

An Android application (the Android project that makes up an Android application) consists primarily of Activity and Service classes and also an xml manifest. In addition, the project contains a ‘res’ (resources) folder which consists of the images (‘res/drawable’), views (‘res/layout’) and strings/styles/colors/arrays/etc (‘res/values’) used within the application and a ‘gen’ folder that contains a static (auto-generated) R class providing design time access to the resources in the ‘res’ folder. We describe below the manifest, and then the Activity and Service components.

Application Manifest

An application’s manifest is an xml file defining the structure and metadata of the application and its components, i.e. its activities and services. The manifest contains only one ‘application’ node which acts as a container to specify the application’s components (i.e. ‘activity’ and ‘service’ nodes). A component must be registered in the manifest in order to be used in the application.

Activity

An activity represents a screen and is the base class for the application’s visual, interactive components. Every screen in an application will extend the Activity class.

When a new Activity starts during the running of an application, the current foreground screen is moved to the top of the ‘Activity stack’. If the user navigates back using the back button, or the foreground Activity is closed, the next Activity on the stack moves up and becomes active.

Android provides a series of event handlers that are fired and for the programmer to take care of an Activity’s transitioning through its different possible lifetimes (‘full’, ‘visible’, ‘active’) and states within those lifetimes (‘active’, ‘paused’, ‘stopped’, ‘inactive’), e.g. onCreate(Bundle), onRestoreInstanceState(Bundle), onStart(), onRestart(), onResume(), onSaveInstanceState(Bundle), onPause(), onStop(), onDestroy(). These methods are to be overridden by the programmer to perform the tasks desired of the activity as it passes through its different lifetimes/states.

Some of the key user interface classes that an activity will make use of are as follows:

  • View:  An Activity uses a View to form a graphical user interface that displays information and responds to user actions. It is the visual component (layout) of an activity and may itself consist of (sub-) views as well as controls/widgets. Views can be defined in code but preferably are defined in xml and stored in the project’s ‘res’ folder. In the latter case, the user interface elements within the view’s definition are given identifier attributes to get access to them in code (via the R class).
  • Menu: Each activity can specify its own Activity menu that’s displayed when the device’s menu button is pressed. A Menu as such offers a way to expose additional functions of an Activity without sacrificing screen space. To define a menu for an Activity, the Activity’s onCreateOptionsMenu(Menu) method is overridden. This method is triggered the first time an Activity’s menu is displayed.
  • Dialogs: A Dialog is a floating window that is constructed entirely within an Activity and which partially obscures from view the Activity that launched it.

Another key class that an Activity will make use of is an Intent, which is used for the transitioning between Activities. It is a message-passing mechanism that declares the intent for an action to be performed. Whilst not the only use for Intents, the most common use is indeed to start, stop and transition between the Activities within an application. The startActivity(Intent) method of the Activity class is used for this purpose and the Intent passed in either explicitly specifies the class to open or includes an action that the target should perform. An Activity started in this way is independent of its parent and will not provide any feedback when it closes. The startActivityForResult(Intent, int) method of the Activity class is an alternative method to start a sub-activity which is inherently connected to its parent.

Service

Services are the invisible workers of an application. Service components perform tasks that run in the background and which do not require a user interface, such as updating data sources and visible Activities, and triggering notifications. They’re used to perform regular processing that needs to continue even when an application’s Activities aren’t active or visible.

(Essay written as a tw hour timed test for the boss at work. Didn’t get time to look at: Bundles, Contexts, Content Providers; Broadcast Receivers; Data Storage, Retrieval and Sharing; Maps etc)

Tuesday, 21 June 2011

App Deployment Tool

Completed the app deployment tool (built as a Windows Presentation Foundation client application) which compiles and deploys (/uploads) an app based on an xml description of the different languages and platforms the app has been built for (where source code for the app can be found, where the app is to be deployed, and so on). Additionally, tool can change version number of app (by declaring the different places in the source code where the version number is specified) as well as change general lines of code and move files around prior to (and as part of) a compile/deploy action.

Technical note: the 'deployment' process is multi-threaded (hence the existence of 'configuration wrapper' classes as well as 'deploy instruction' classes). The 'compilation' process on the other hand is single-threaded.

Description of the two main deploy actions:
GroupAction - Uploads each of the files/directories specified individually from the source locations to the target location, clearing the target of all its contents prior to the upload if this option has been specified.
BuildAction - Builds the gadget/zip from the source files/directories specified (according to the platform the gadget is being built for), naming the build as specified, and then uploads the build to the target location, clearing the target of all its contents prior to the upload if this option has been specified.

Description of the two main compile actions:
AndroidCompileAction - Compiles the Android project found at the project location specified and then moves (and renames) the 'apk' file built from the project's 'bin' folder (which is cleared with each compilation) to the compile rename path specified.
GWTCompileAction - Compiles the GWT project found at the project location specified according to the class paths and modules specified.

Additional actions which can be specified within the above four main actions: ChangeVersionNumberInCode,  ChangeLineInCode, CopyFileAction, CopyDirectoryContentsAction.

Thursday, 9 June 2011

Katana Sales System

Just finished the Katana Sales System for Katana management to keep track of contact/actions with individuals at specific agencies and also to keep track of the different work (case studies) done by the different agencies for the various clients they have worked for. System built using Microsoft Sql Server 2008 (database tables and stored procedures), Microsoft Visual Studio 2010 (data access layer and serving web requests) and Google Web Toolkit (client-side web interface). Built the client-side web app loosely based on the Model-View-Presenter architecture.

Wednesday, 25 May 2011

App Metrics System (Notes)

Some brief notes on the flow of information in the app metrics system I'm working on so that I remember how it works when I come back to it...

(1) An app is selected in the gui from the list of apps/projects that the user has access to.

(2) A request is sent to the server to get the xml config page which contains the css styles and the markup/layout for each of the pages (including the list of widgets contained).

(3) The xml config page is rendered on the gui and for the default ('dashboard') page a request is sent to the server to get the values for each of the widgets.

(4) A subsequent request is sent for widget values is sent to the server for each of the other pages the first time they are selected and also when refreshed.

Tuesday, 17 May 2011

Sql server column and stored procedure data types

Given a table with a column 'postcode' (for example) taking data type 'varchar(20)' and a stored procedure taking parameter '@postcode' of type 'varchar(max)'. Passing a string of length larger than 20 will throw up an exception.

On the other hand, given a table with a column 'postcode' taking data type 'varchar(20)' and a stored procedure taking parameter '@postcode' of type 'varchar(20)'. Passing a string of length larger than 20 will truncate and insert the string no problem.

Tuesday, 26 April 2011

WPF Binding Controls

Tried binding some checkboxes to a "check all" checkbox as below and it worked fine except that when a bound checkbox is clicked the binding gets lost. Not what I was intending but apparently this is how 'OneWay' binding behaves. There were some workarounds but I thought it easier in the end to do what I wanted without binding and instead to add good old-fashioned "Checked" and "Unchecked" event handlers to the "check all" checkbox.

Code I was using before...
Binding binding_isChecked = new Binding("IsChecked");
binding_isChecked.ElementName = "cbCheckAll";
binding_isChecked.Mode = BindingMode.OneWay;
DependencyProperty property_isChecked = CheckBox.IsCheckedProperty;

Binding binding_isNotChecked = new Binding("IsChecked");
binding_isNotChecked.ElementName = "cbCheckAll";
binding_isNotChecked.Mode = BindingMode.OneWay;
BoolToOppositeBoolConverter boolConverter = new BoolToOppositeBoolConverter();
binding_isNotChecked.Converter = boolConverter;
DependencyProperty property_isEnabled = CheckBox.IsEnabledProperty;

cb.SetBinding(property_isChecked, binding_isChecked);
cb.SetBinding(property_isEnabled, binding_isNotChecked);
Code I'm using now...
cb.Checked += delegate
{
foreach (CheckBox checkBoxInStackPanel in sp.Children)
{
if (!checkBoxInStackPanel.Content.Equals(cbCheckAllContent))
{
checkBoxInStackPanel.IsChecked = true;
checkBoxInStackPanel.IsEnabled = false;
}
}
};

cb.Unchecked += delegate
{
foreach (CheckBox checkBoxInStackPanel in sp.Children)
{
if (!checkBoxInStackPanel.Content.Equals(cbCheckAllContent))
{
checkBoxInStackPanel.IsChecked = false;
checkBoxInStackPanel.IsEnabled = true;
}
}
};

Monday, 14 March 2011

WeightTracker Localisation Checklist

Checklist of things to do when creating language assets for a new locale upon receiving string and image files:

(1) Android strings: Need to copy in...
(a) '..._helpText_...'
(b) '..._facebookpost_...'
... strings from the gwt strings file, and need to put in...
(c) 'mobile_2_newentry_1_b_2_UK_ONLY_RadioButton' (if missing)
(d) 'url_...'
(e) 'fbpost_...'
(f) 'marketHelpline' (null value if 'mobile_6_options_1_a_5_disclaimer' doesn't have a 'marketHelpline' string placeholder)
(g) 'stones'
(h) 'pounds'
(i) 'kilograms'
... key-value pairs, and need to manually tinker with...
(j) 'mobile_5_goal_2_update_1_a_3_Paragraph' (change placeholder to "{n}")
(k) 'web_6_help_1_a_2_helpText_1' (put in [] placeholder)
strings. See the equivalent English strings for examples.

(2) Android images: Create folders (hdpi, ldpi, mdpi) in language assets for the locale specific images for the language in question.

(3) GWT strings: Need to put in and fix up
(a) 'url_...'
(b) 'region_...'
(c) 'fbpost_...'
(d) 'mobile_2_newentry_1_a_8_feeling'
strings, and remember to combine
(e) 'web_dashboardscreen_e_1_Paragraph_0'
with
(f) 'web_dashboardscreen_e_1_Paragraph_1'
and remove extra sentence (if extra sentence there) from
(g) 'web_homescreen_c_2_Paragraph_0'
string, and remember to add [] text placeholders in
(h) 'web_dashboardscreen_c_1_Paragraph_0'
(i) 'web_6_help_1_a_2_helpText_1'
(j) 'web_3_editgoal_1_a_8_Paragraph' (change placeholder to "{n}")
(k) 'web_3_editgoal_1_b_7_Paragraph' (change placeholder to "{n}")
(l) 'web_homescreen_b_2_Paragraph'
strings. See the equivalent English strings for examples.

(4) GWT Windows: Create folder in language assets to contain
(a) Locale-specific 'docked_bg.png' image.
(b) 'war/WeightTracker_WINDOWS_flyout.html' and 'war/WeightTracker_WINDOWS.html' files. Remember to change 'alli_locale' meta-variable as appropriate.
(c) 'war/gadget.xml' file. Remember to change 'name', 'info url' and 'description' properties as appropriate.

(5) GWT Mac: Create folder in language assets to contain
(a) 'war/WeightTracker_MAC.html' file. Remember to change 'alli_locale' meta-variable as appropriate.
(b) 'war/Info.plist' file. Remember to change 'CFBundleDisplayName' key value as appropriate.

(6) Server facebook resources: Add 'btnFBLogin_xx.png' and 'fbcrossdomain_xx.aspx' for the region (xx) being added, as well as any other images and files required.

When deploying the Android, Mac and/or Windows app/gadget for a particular locale, copy in the required "language assets" to the 'war' folder for the GWT Mac and Windows gadgets and to the 'res' folder for the Android app. Additionally, for the Android app:
(1) Change 'ALLI_LOCALE' variable in 'AlliCore/User.java'.
(2) Change 'CURRENT_REGION' variable in 'AlliCore/User.java'.

Notes for future:
(i) Create string with value "Saving. Please wait..." (and remember to include in translations).
(ii) Create string with value "Account Error" (and remember to include in translations).

Friday, 4 March 2011

WeightTracker app different Web.config files

Web.config - local test
Web.config2 - our online one for our servers/api/db
Web.config3 - our servers; their api
Web.config4 - their servers; their api

Thursday, 24 February 2011

How to debug a facebook app using eclipse (gwt)

Steps to get a facebook app (written using google web toolkit) to run on the Visual Studio server and be picked up by the Eclipse debugger:

(1) Go to app developer page (e.g. http://www.facebook.com/developers/apps.php?app_id=168754973148732).

(2) Check and edit app settings as necessary. Look out for Facebook Integration settings (and Canvas URL setting) in particular. (Example Canvas URL value: http://127.0.0.1:21024/fb/)

(3) Navigate to app (Canvas Page) and append "index.html" or similar page to url. (Example Canvas Page value: http://apps.facebook.com/gskallitest/) Reload page.

(4) Use Google Chrome or Mozilla Firefox 'Inspect Element' tool to select the app in the page (it might not be visible but will be present in the html markup).

(5) Find the app iframe in the page html markup and pull out the src url. Bung in between "...index.html?" and "signed_request=..." the text "gwt.codesvr=127.0.0.1:9997&".

(6) Stick this modified url into your browser and assuming you have your gwt project running/debugging on Eclipse you're good to debug :)>

Note: When running the facebook project on eclipse (as a web application), uncheck the 'run built-in server' option from the Debug Configurations dialog ('Server' tab) and specify instead the server url to run from ('GWT' tab), i.e. the Canvas URL as specified in step 2.

ps. Remember to change the facebook app settings (step 2) back after testing/debugging. In particular: the Canvas URL setting which should be http://alli2.gsk.kickstartdigital.co.uk/fb/ or similar.