android_logo

Take Photo Using ACTION_IMAGE_CAPTURE Intent

2

In this post we will build a working sample app that allows the user to press a button to take a photo using the phone’s camera app (or any other available) and then loads this photo into an ImageView. You could of course do anything you like with the photo such as upload it to a web service or save it to permanent storage.

Begin by creating a new Android project, then open up your main.xml layout file and edit it. The below xml creates an ImageButton and an ImageView. Everything we need for the sample. The ImageView references a placeholder image.. just a little snap of someone I spotted the last time I was at the beach. :-)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="center_horizontal"
    android:background="#FFFFFF">

    <ImageButton
    	android:id="@+id/btn_take_photo"
    	android:src="@android:drawable/ic_menu_camera"
    	android:layout_width="60dp"
    	android:layout_height="60dp"
    	android:layout_marginTop="10dp"
    	android:layout_marginBottom="5dp" />

    <ImageView
    	android:id="@+id/img_main"
    	android:src="@drawable/kiss_from_a_rose"
    	android:layout_height="wrap_content"
		android:layout_width="fill_parent"
    	android:scaleType="fitXY"
    	android:adjustViewBounds="true"
    	android:padding="5dp" />

</LinearLayout>

In your Activity’s onCreate() method, attach a listener to the button. When the button is clicked we want to start an ACTION_IMAGE_CAPTURE Intent using startActivityForResult().

findViewById(R.id.btn_take_photo).setOnClickListener(new OnClickListener() {
	@Override
	public void onClick(View v) {
		Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
		startActivityForResult(i, REQ_CODE_PHOTO_TAKE);
	}
});

You’ll also need to create the REQ_CODE_PHOTO_TAKE constant. This value will be returned in the resultCode.

private static final int REQ_CODE_PHOTO_TAKE = 1;

Next up push Alt+Shift+S and click “Override/Implement Methods” from the menu. Choose to Override onActivityResult() and click ok.

You’ll notice this method has three parameters. ‘resultCode’ is self explanatory – if this is anything other than RESULT_OK we’ll want to return immediately. An example where this might happen is if the user were to push the button to take a photo but then push their phone’s back button immediately rather than take one. requestCode contains the value that we passed in during startActivityForResult(), in our case this is REQ_CODE_PHOTO_TAKE. Lastly is the returned Intent. We can use this to get a Uri to the data by calling getData().

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
	super.onActivityResult(requestCode, resultCode, data);	

	if(resultCode != RESULT_OK) return;

	switch (requestCode) {
	case REQ_CODE_PHOTO_TAKE:
		Uri u = data.getData();
		onPhotoReturned(u);
    	break;
	default:
		break;
	}
}

Lastly we’ll want to display the photo in our ImageView. Create the new method, onPhotoReturn(Uri u). We use the Uri to open an InputStream and from this we can create a BitmapDrawable which can be used to set the Drawable for the ImageView.

private void onPhotoReturned(Uri u) {
	InputStream is = null;
	try {
		ContentResolver cResolver = getContentResolver();
		is = cResolver.openInputStream(u);
	} catch (FileNotFoundException e) {
		e.printStackTrace();
	}
	BitmapDrawable bmp = new BitmapDrawable(is);
	ImageView mainImage = (ImageView)findViewById(R.id.img_main);
	mainImage.setImageDrawable(bmp);
}

Working code for this app can be found on my github and a screenshot of it in action is below:

TakePhotoExample

TakePhotoExample

Broken Android

Do not use City Main Administrators or The Fone Clinic

13

Since purchasing my HTC Desire nearly 18 months’ ago I’ve had insurance through Citymain Administrators. It’s £5.99 a month and covers me for theft and accidents. The service from their call centre has been all in all quite good since I dropped and broke the screen on my phone on September 15th 2011, unfortunately the company they use for repairs has now taken almost three weeks to repair my phone. I was told last Friday that my phone was finally being repaired – after being told this I kind of expected it to arrive Saturday or Monday. That’s a reasonable expectation in a world that expects good customer service, no? Monday 3rd October I was told it was repaired but waiting to be posted to me. Today, Wednesday 5th October I was told that it was still waiting to be posted to me and this should hopefully happen tomorrow. If this holds true – and I have my doubts – then I’ll get my phone back on Friday which makes it three weeks. The worst part is the length of time that I know my phone has been sat idle.

They don’t appear to be a small outfit either, covering units 18 – 20 in the picture below. You’d think someone could post a phone for a customer regularly chasing and specifically requesting it be returned in time for Droidcon tomorrow?

thefoneclinic

thefoneclinic

From this experience I will soon be cancelling my policy with Citymain Administrators and do not recommend you use either them or The Fone Clinic in Southend-On-Sea.

If anyone can recommend to me a UK phone insurance policy that doesn’t let you down when it comes to needing a repair, please let me know…

Android

Android: Use GreenDroid to implement an ActionBar

15

This post covers the basics of setting up a project using the GreenDroid library including pulling it from GitHub and how to use the ActionBar it provides. GreenDroid is a useful UI library for Android developed by Cyril Mottier. You can check out all the features it provides by downloading the GDCatalog app from the Android Market.

The action bar:

  • is located at the top of the screen to support navigation and highlight important functionalities
  • replaces the title bar (which is often included into it)
  • is best used for actions across your app, like search, refresh and compose
  • can provide a quick link to app home by tapping the app logo
  • is preferably not contextual, but actions can differ from page to page

Android Patterns

If you don’t have EGit in Eclipse. You’ll need to install it. See here. Begin by opening the “Git Repository Exploring” perspective. Window > Open Perspective. Click the button for “Clone a Git Repository and add the clone to this view” and paste in this to the URI field: https://github.com/cyrilmottier/GreenDroid.git – the rest of the details should be filled in automatically, so hit next and follow the wizard through. It’s likely you won’t need to change anything.

You’ll notice the GreenDroid repository is now available to you. Open out the branches GreenDroid > Working directory, right click the folder ‘GreenDroid’ and select ‘Import Projects’. Follow the dialog through and click finish. Switch back to the Java Perspective and you will now have the GreenDroid project imported. You will likely have a problem with the project’s ‘gen’ folder or R.java. If you do (an exclamation mark or cross next to the project name), delete it and then recreate a new folder called gen, if not, create the folder. I also had to right click the project, Android Tools > Fix Project Properties to get it working as it was targeting a different compiler version to mine.

Next up create your new Android Project, the build target will need to be a minimum of 1.6 to use GreenDroid. Right click on your newly created project, select Properties, then select Android on the left hand side of the dialog. At the bottom of the window you can click “Add..” and you should have the option to select GreenDroid as a library. Click OK.

Change your default Activity to extend GDActivity. Wherever you want to use the GreenDroid ActionBar your class will need to extend GDActivity, GDListActivity or GDTabActivity. You will also need to remember to no longer call setContentView() to set your layout and instead use setActionBarContentView(). The former will crash your Activity. Change these and hit ctrl+shift+o to organise your imports.

public class GreenDroidActionBarExampleActivity extends GDActivity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setActionBarContentView(R.layout.main);
    }
}

Next add a new class to your project that extends GDApplication. Override the getHomeActivityClass() method and the getMainApplicationIntent() methods. The former will need to return your main home/launcher activity and the latter will return an Intent to view the relevant website for your app:

public class GDActionBarExampleApplication extends GDApplication {

    @Override
    public Class<?> getHomeActivityClass() {
        return GreenDroidActionBarExampleActivity.class;
    }

    @Override
    public Intent getMainApplicationIntent() {
        return new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.app_url)));
    }

}

You will also need to add the the app_url string to your res/values/strings.xml file:

<string name="app_url">http://www.samcoles.co.uk</string>

Next update your AndroidManifext.xml to use your new Application class:

<application android:icon="@drawable/icon"
     			android:label="@string/app_name"
     			android:name=".GDActionBarExampleApplication">

Right click your res/values folder and create a new xml values file, call it themes.xml. In here we will specify some app-wide styles for your ActionBar. Ignore the error on the gdActionBarApplicationDrawable and gdActionBarBackground value for now:

<?xml version="1.0" encoding="utf-8"?>
<resources>
	<style name="Theme.GDActionBarExample" parent="@style/Theme.GreenDroid.NoTitleBar">
		<item name="gdActionBarTitleColor">#FFFDD0</item>
		<item name="gdActionBarBackground">@drawable/action_bar_background</item>
		<item name="gdActionBarDividerWidth">2px</item>
		<item name="gdActionBarApplicationDrawable">@drawable/application_logo</item>
	</style>
</resources>

Again, update the application tag in your AndroidManifest.xml to use this theme:

<application android:icon="@drawable/icon"
     			android:label="@string/app_name"
     			android:theme="@style/Theme.GDActionBarExample"
     			android:name=".GDActionBarExampleApplication">

Back to the error in themes.xml. It is clear that you could just place an image into your drawable folders called application_logo. But we are going to use a StateDrawable xml so that the logo behaves like a button. Create a folder, /res/drawable and within here create two new xml files called application_logo.xml and action_bar_background.xml, the latter will be a ShapeDrawable for our ActionBar’s background. In application_logo.xml place your state drawable code that defines the image to use for pressed, focused and normal states:

<?xml version="1.0" encoding="utf-8"?>
<selector
	xmlns:android="http://schemas.android.com/apk/res/android">

	<item
		android:state_pressed="true"
		android:drawable="@drawable/application_logo_alt" />

	<item
		android:state_focused="true"
		android:drawable="@drawable/application_logo_alt" />

	<item
		android:drawable="@drawable/application_logo_normal" />

</selector>

and in action_bar_background.xml the ShapeDrawable code. This is just a solid block of colour, but you could specify a gradient or even use an image:

<?xml version="1.0" encoding="utf-8"?>

<shape
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:shape="rectangle">

	<solid android:color="#708090" />

</shape>

Next you will need to place the images you’ve specified in the application_logo.xml StateDrawable into your project. The GDCatalog app uses the dimensions of 205×51 pixels for the hdpi versions and 135×34 for the mdpi version. I haven’t yet needed to experiment with different sizes so mine are the same dimensions, and these suit the ActionBar proportions well. Place these into the relevant res/drawable-hdpi and res/drawable-mdpi folders.

You should now be able to run the project and test it out! It won’t look much but you can tap the logo and it should open the URL specified in your app_url string. Notice also that it changes to your application_logo_alt.png image when touched or selected.

Next we will make the ActionBar a little more useful by adding a button to it that will take us to our application’s info activity. Back in GreenDroidActionBarExampleActivity, simply add an info button by placing this call in your onCreate() method:

addActionBarItem(Type.Info, ACTION_BAR_INFO);

Also add that constant to the top of your class:

private static final int ACTION_BAR_INFO = 0;

Go ahead and run it again. The info button is in! But you’ll notice that nothing happens when you click it.

To enable this button to do something we need to override onHandleActionBarItemClick(). Right click your Activity, source > Override/Implement methods and choose it from the options under GDActivity. You can get the value of the id that was passed in the second parameter of addActionBarItem  by calling getItemId() on the item. So create a switch block on this value and start InfoActivity (we’ll create this next) if the info button has been pressed:

@Override
public boolean onHandleActionBarItemClick(ActionBarItem item, int position) {
	switch(item.getItemId()) {
	case ACTION_BAR_INFO:
		startActivity(new Intent(this, InfoActivity.class));
		break;
	default:
		return super.onHandleActionBarItemClick(item, position);
	}
	return true;
}

Create the new class InfoActivity that extends GDActivity, and don’t forget to add it to your manifest.

<activity android:name=".InfoActivity"></activity>

In your onCreate() method of InfoActivity set the title to be displayed in the Action Bar:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setActionBarContentView(R.layout.main);
    setTitle(R.string.info_activity_title);
}

Remember to add this string to your strings.xml file also:

<string name="info_activity_title">App Info</string>

Now run your app! Notice that the InfoActivity Action Bar has a home button and a title in place of the application logo. Tap the home button to return to the home activity you just came from.

Working Android 1.6 source for this post is available on github. To checkout the other features of GreenDroid you can also import the project for the GDCatalog app from the GreenDroid github repository.

Action Bar Using GreenDroid

Action Bar Using GreenDroid

InfoActivity

InfoActivity

androidify

Android: Simple Full Screen Image Viewer Activity

0

Here’s the code for a simple full screen ImageViewerActivity. It uses the SDImageLoader from this post to load the image asynchronously from the SD card.

public class ImageViewerActivity extends Activity {

	public static final String IMAGE_PATH = "imagevieweractivityfilepath";

	private final SDImageLoader mImageLoader = new SDImageLoader();

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.imageviewer);
		Bundle extras = getIntent().getExtras();
		if(extras != null) {
			String imagePath = extras.getString(IMAGE_PATH);
			if(imagePath != null) {
				ImageView i = (ImageView)findViewById(R.id.image_viewer_image);
				mImageLoader.load(this, imagePath, i);
			}
		}
	}

}

Here’s an example of how to use this activity:

//load the filepath from the database
Cursor c = mDbHelper.fetchCapture(info.id);
String filePath = c.getString(c.getColumnIndexOrThrow(SpecimenHunterDatabaseAdapter.KEY_CAPTURES_PHOTO));
//create the new intent
Intent it = new Intent(this, ImageViewerActivity.class);
//put the filepath into the extras bundle
it.putExtra(ImageViewerActivity.IMAGE_PATH, filePath);
//start activity.
startActivity(it);

Here’s the xml layout file. Use the src of the ImageView to set the image to use as a placeholder while the image you wish to display loads from the SD card.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:orientation="vertical"
	android:layout_width="fill_parent"
	android:layout_height="fill_parent"
	android:layout_weight="1"
	android:layout_gravity="center"
	android:gravity="center">

	<ImageView
		android:id="@+id/image_viewer_image"
		android:src="@drawable/thumbnail_placeholder"
		android:layout_width="fill_parent"
		android:layout_height="fill_parent"
		android:adjustViewBounds="true"
		android:layout_gravity="center"
		android:gravity="center" />

</LinearLayout>
icon72x72

Android: ‘Specimen Hunter’ – Fishing App for UK Coarse Anglers

2

Available in Android Market

A short while back I built an Android app for UK (& European) Coarse Anglers. More recently I’ve had it tarted up with some nice graphics by Olie Kay and pushed it to the Android Market.

The current fish capture logging apps that are out there for Android quite admirably try to achieve ‘the kitchen sink’, but end up being quite heavy and difficult to use. Specimen Hunter aims to simplify things and focuses on your targets and tracking personal bests.

Please check out the app and see what you think. It’s free – if you like it, you can offer your support simply by rating it or reccomending it to friends. It’s actively being developed, so if you have any suggestions, feature requests or spot any bugs please leave a comment on this post, or contact me via email or twitter and I’ll get back to you ASAP.

Features:

  • Set yourself specimen targets
  • Log your specimen captures
  • Review and sort your logged captures
  • Automatically review all your personal bests
  • Share info with other apps (email/twitter etc.)
  • Post your captures to your facebook wall from within the app
  • Active development – contact the dev with your ideas and suggestions!

 

Click here to install Specimen Hunter.

 

Specimen Hunter Dashboard

Specimen Hunter Dashboard

Specimen Hunter Targets

Specimen Hunter Targets

Specimen Hunter Personal Bests

Specimen Hunter Personal Bests

android_logo

Android: Using a custom font

0

Can you set a custom font from XML? As far as I’ve managed to find, the answer is no.

So instead, how do you do this programatically?

First start by creating an ‘assets’ folder in your project, within this create a folder called ‘fonts’. ‘assets’ should be on the same level as ‘res’ and not within it. Drag your font file in here. Need a font? Lots of free, open source ones available here: http://www.google.com/webfonts/v2.

Setting the font on a View couldn’t be simpler, here’s an example using the Lobster font from Google webfonts

TextView someTextView = (TextView)findViewById(R.id.some_text_view_id);

Typeface tf = Typeface.createFromAsset(getAssets(), "fonts/Lobster.ttf");
someTextView.setTypeface(tf);

If needing to set the font in a list item, I load the font to a member variable within the constructor of my ListAdapter so that it can be used in my overridden newView() rather than loading it every time.

Android

Android: Retain values on orientation change

0

When you change the orientation of your phone. The current activity is destroyed via onDestroy() and then recreated with onCreate() being called. This presented a problem for me with a list that has different ways of sorting – I wanted this sorted order to persist while the current activity was open, but there was no need for it to do so when coming to the activity again. Here’s a quick demonstration of how to achieve this.

The type of sort to do is stored in a member variable. This uses constants from my Database Adapter class. When the data is pulled from the database, this sort code is passed in and used by the DB Adapter, data is returned sorted correctly. When the phone’s orientation is changed we want the list to remain sorted in the same order.

private Integer mListSortCode;

Next in your activity, override onRetainNonConfigurationInstance(). This method is called just before onDestroy(). In my example I need only one value so I made the mListSortCode an Integer object. It’s easy to see how you could create an inner class that would hold all the data you need to retain and use it here.

@Override
public Object onRetainNonConfigurationInstance() {
    final Integer sortcode = mListSortCode;
    return sortcode;
}

In your onCreate() method call getLastNonConfigurationInstance() to get a reference to this object and cast it to the correct type. If onCreate() is being called because of any reason other than an orientation change it will be null, so check for this and handle appropriately:

final Integer previousConfigSortCode = (Integer)getLastNonConfigurationInstance();
if (previousConfigSortCode != null) {
    mListSortCode = previousConfigSortCode;
} else {
    //set to default
    mListSortCode = SpecimenHunterDatabaseAdapter.SORT_NONE;
}

 

Spinner In Action

Android: populate a Spinner from a SQLite database

22

Here’s a bit of code to populate a spinner with data from a database. The database table contains info about all the different species of fish within my app. I want the user to choose the species from the spinner and then the ID of that species is then stored as a foreign key within my ‘captures’ table.

First start by defining the spinner in your xml layout, here’s the example from my layout:

<Spinner
    android:id="@+id/spinner_species"
    android:layout_height="wrap_content"
    android:layout_width="fill_parent"
    android:prompt="@string/addcapture_species_prompt" />

From your Activity, within your onCreate() method, get a reference to the spinner and a Cursor to all your species from your database. Pass your cursor into startManagingCursor() to let your Activity take care of it:

Spinner speciesSpinner = (Spinner)findViewById(R.id.spinner_species);
Cursor speciesCursor = mDbAdapter.fetchAllSpecies();
startManagingCursor(speciesCursor);

Create a SimpleCursorAdapter to bind the text you want to be displayed on your spinner to the textview display on your spinner and set this to the spinner. SpecimenHunterDatabaseAdapter.KEY_SPECIES_NAME is a String constant of the name of the column in my database containing the name. android.R.layout.simple_spinner_item is a predefined Android layout for the spinner and android.R.id.text1 is the textview defined within this. android.R.layout.simple_spinner_dropdown_item is our layout for the items in the menu that appears when you tap the spinner.

String[] from = new String[] { SpecimenHunterDatabaseAdapter.KEY_SPECIES_NAME };
int[] to = new int[] { android.R.id.text1 };
SimpleCursorAdapter speciesSpinnerAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_spinner_item, speciesCursor, from, to);
speciesSpinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
speciesSpinner.setAdapter(speciesSpinnerAdapter);

When the user selects an option on the spinner, we need store that somewhere. Create a member in your Activity to hold the value:

private int mSpinnerSpeciesId;

Lastly, back in your onCreate() method below the call to setAdapter() we need to attach an OnItemSelectedListener to the spinner. The method onItemSelected() will be called when the selected item on the spinner changes – it’s also called when your activity starts with the first value on the spinner’s list.

speciesSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
        Cursor c = (Cursor)parent.getItemAtPosition(pos);
        mSpinnerSpeciesId = c.getInt(c.getColumnIndexOrThrow(SpecimenHunterDatabaseAdapter.KEY_SPECIES_ROWID));
    }
    @Override
        public void onNothingSelected(AdapterView<?> parent) {
    }
});

Here’s the spinner in action after being pressed:

Spinner In Action

Spinner In Action

Asynchronously Loaded Images in ListView

Android: Asynchronously Load Image from SD card

6

Trying to load images from the SD card into my listview within the UI thread (directly in bindView())made scrolling the listview very jerky and slow – it worked but was barely acceptable. My initial attempt at asynchronously loading the images from the SD card ran into a bit of a problem when I discovered that the Views for each row on a list are reused when they go off screen as initialising the Views is a costly process. This meant with the way I’d written my code that quickly scrolling the list would cause the ImageView to flicker between all the other images I’d loaded into it before settling on the final one. This is because all the AsyncTasks that’d been created were yet to finish and calling onPostExecute() binding the view before a new one was created!

So I looked into how to solve this problem. The code/tutorial in the post, Multithreading For Performance on the Android Developer blog, asynchronously downloads/binds an image from the Internet. I’ve adapted this to load the image from the SD card. Here’s my class, SDImageLoader:

package com.samcoles.specimenhunter.ui;

import java.lang.ref.WeakReference;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.widget.ImageView;

public class SDImageLoader {

	public void load(String filePath, ImageView v) {
		if(cancelPotentialSDLoad(filePath, v)) {
			SDLoadImageTask task = new SDLoadImageTask(v);
			SDLoadDrawable sdDrawable = new SDLoadDrawable(task);
			v.setImageDrawable(sdDrawable);
			task.execute(filePath);
		}
	}

	private Bitmap loadImageFromSDCard(String filePath) {

		BitmapFactory.Options bfo = new BitmapFactory.Options();
        bfo.inSampleSize = 4;
        bfo.outWidth = 150;
        bfo.outHeight = 150;
		Bitmap photo = BitmapFactory.decodeFile(filePath, bfo);
		return photo;
	} 

	private static boolean cancelPotentialSDLoad(String filePath, ImageView v) {
		SDLoadImageTask sdLoadTask = getAsyncSDLoadImageTask(v);

		if(sdLoadTask != null) {
			String path = sdLoadTask.getFilePath();
			if((path == null) || (!path.equals(filePath))) {
				sdLoadTask.cancel(true);
			} else {
				return false;
			}
		}
		return true;
	}

	private static SDLoadImageTask getAsyncSDLoadImageTask(ImageView v) {
		if(v != null) {
			Drawable drawable = v.getDrawable();
			if(drawable instanceof SDLoadDrawable) {
				SDLoadDrawable asyncLoadedDrawable = (SDLoadDrawable)drawable;
				return asyncLoadedDrawable.getAsyncSDLoadTask();
			}
		}
		return null;
	}

	private class SDLoadImageTask extends AsyncTask<String, Void, Bitmap> {

		private String mFilePath;
		private final WeakReference<ImageView> mImageViewReference;

		public String getFilePath() {
			return mFilePath;
		}

		public SDLoadImageTask(ImageView v) {
			mImageViewReference = new WeakReference<ImageView>(v);
		}

		@Override
		protected void onPostExecute(Bitmap bmp) {
			if(mImageViewReference != null) {
				ImageView v = mImageViewReference.get();
				SDLoadImageTask sdLoadTask = getAsyncSDLoadImageTask(v);
				// Change bitmap only if this process is still associated with it
				if(this == sdLoadTask) {
					v.setImageBitmap(bmp);
				}
			}
		}

		@Override
		protected Bitmap doInBackground(String... params) {
			mFilePath = params[0];
			return loadImageFromSDCard(mFilePath);
		}
	}

	private class SDLoadDrawable extends ColorDrawable {
		private final WeakReference<SDLoadImageTask> asyncSDLoadTaskReference;

		public SDLoadDrawable(SDLoadImageTask asyncSDLoadTask) {
			super(Color.BLACK);
			asyncSDLoadTaskReference = new WeakReference<SDLoadImageTask>(asyncSDLoadTask);
		}

		public SDLoadImageTask getAsyncSDLoadTask() {
			return asyncSDLoadTaskReference.get();
		}

	}
}

To use this, within your list adapter create an SDImageLoader as a member:

private final SDImageLoader mImageLoader = new SDImageLoader();

and within your overridden bindView() method simply call the method load, passing it a string representing the absolute filepath and the ImageView you want it to be loaded into. e.g.

mImageLoader.load(photoFilePath, photoView);

Here’s that in action:

Asynchronously Loaded Images in ListView

Asynchronously Loaded Images in ListView

A working example project based on this post can be found on github.

Android

Android: Lock and unlock screen orientation

15

Need to temporarily lock the screen orientation on your app? When calling setRequestedOrientation() on your activity, it will no longer allow the orientation to change even when the phone is rotated. So check what the current orientation of the screen is and set it to the same orientation with setRequestedOrientation()

public static void lockCurrentScreenOrientation(Activity a) {

	if(a.getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
		a.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
	} else {
		a.setRequestedOrientation(a.getRequestedOrientation());
	}
}

To unlock it again, pass ActivityInfo.SCREEN_ORIENTATION_USER:

public static void unlockScreenOrientation(Activity a) {
	a.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER);
}
Go to Top