Thursday, 31 May 2012

Android: creating a Drawable or a Bitmap from a web url

Here are a couple of methods for creating a Drawable or a Bitmap from a web url:

/** Returns a Drawable object containing the image located at 'imageWebAddress' if successful, and null otherwise.
 * (Pre: 'imageWebAddress' is non-null and non-empty;
 * method should not be called from the main/ui thread.)*/
public static Drawable createDrawableFromUrl(String imageWebAddress)
{
  Drawable drawable = null;

  try
  {
    InputStream inputStream = new URL(imageWebAddress).openStream();
    drawable = Drawable.createFromStream(inputStream, null);
    inputStream.close();
  }
  catch (MalformedURLException ex) { }
  catch (IOException ex) { }

  return drawable;
}

/** Returns a Bitmap object containing the image located at 'imageWebAddress'
 * if successful, and null otherwise.
 * (Pre: 'imageWebAddress' is non-null and non-empty;
 * method should not be called from the main/ui thread.)*/
public static Bitmap createBitmapFromUrl(String imageWebAddress)
{
  Bitmap bitmap = null;

  try
  {
    InputStream inputStream = new URL(imageWebAddress).openStream();
    bitmap = BitmapFactory.decodeStream(inputStream);
    inputStream.close();
  }
  catch (MalformedURLException ex) { }
  catch (IOException ex) { }

  return bitmap;
}

Friday, 27 January 2012

Android: getting text to roll (marquee animate) in TextView

Set the following TextView properties in your xml layout file…

<TextView
 …
 android:id="@+id/myTextView"
 android:singleLine="true"
 android:ellipsize="marquee"
 android:marqueeRepeatLimit="marquee_forever"
 android:focusable="true"
 android:focusableInTouchMode="true"
 … />

… and now whenever the width of the text in the TextView is longer than the width of the TextView itself, the text will roll right to left along the TextView repeatedly. The number of times the animation repeats is determined by the integer value you set marqueeRepeatLimit to.

Note that sometimes the above is not sufficient and you need to make the following call in your code:
myTextView.setSelected(true);

Done!

Thursday, 26 January 2012

Android: using ViewSwitcher with in and out animations

In your xml layout file, you'll want something like the followng…

<ViewSwitcher
 android:id="@+id/viewSwitcher"
 android:inAnimation="@android:anim/slide_in_left"
 android:outAnimation="@android:anim/slide_out_right"
 … >
<View
 android:id="@+id/myFirstView"
 … />
<View
 android:id="@+id/mySecondView"
 … />

… This defines a ViewSwitcher which slides the next View to be shown in from the left and slides the current View out to the right.

In your code then where this layout file is referenced, you can initialise your Views as follows...

ViewSwitcher viewSwitcher =
 (ViewSwitcher)findViewById(R.id.viewSwitcher);
View myFirstView = findViewById(R.id.myFirstView);
View mySecondView = findViewById(R.id.mySecondView);

… And define some helper methods like the following to toggle between the two Views…

void showFirstView()
{
 if (viewSwitcher.getCurrentView() != myFirstView)
  viewSwitcher.showPrevious();
}

void showSecondView()
{
 if (viewSwitcher.getCurrentView() != mySecondView)
  viewSwitcher.showNext();
}

Done! And I guess the above applies equal well for ViewFlipper too.

Other animations are available too like fading in and fading out. Check out the following reference:
http://developer.android.com/reference/android/R.anim.html

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".