[Java for Android App Development] matt95:
I'm trying to make an app that displays and image which will be downloaded in background in an IntentService class. When the IntentService finishes to download it sends the intent to be catched by a BroadcastReceiver in the MainActivity but I'm getting this error:

07-17 14:27:21.003 19189-19189/com.example.matt95.myapplication E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.example.matt95.myapplication, PID: 19189
java.lang.RuntimeException: Error receiving broadcast Intent { act=TRANSACTION_DONE flg=0x10 (has extras) } in com.example.matt95.myapplication.MyActivity$1@41a982f8
at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java)
at android.os.Handler.handleCallback(Handler.java)
at android.os.Handler.dispatchMessage(Handler.java)
at android.os.Looper.loop(Looper.java)
at android.app.ActivityThread.main(ActivityThread.java)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at com.example.matt95.myapplication.MyActivity$1.onReceive(MyActivity.java:74)
************at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java)
************at android.os.Handler.handleCallback(Handler.java)
************at android.os.Handler.dispatchMessage(Handler.java)
************at android.os.Looper.loop(Looper.java)
************at android.app.ActivityThread.main(ActivityThread.java)
************at java.lang.reflect.Method.invokeNative(Native Method)
************at java.lang.reflect.Method.invoke(Method.java)

This is MainActivity class:

package com.example.matt95.myapplication;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ImageView;
import android.widget.Toast;

import java.io.File;

public class MyActivity extends Activity {

ProgressDialog pd;

// Custom BroadcastReceiver for catching and showing images

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
}

@Override
protected void onStart() {
super.onStart();
Intent i = new Intent(this, ImageIntentService.class);
i.putExtra("url", "http://samsung-wallpapers.com/uploads/allimg/130527/1-13052F02118.jpg");
startService(i);
pd = ProgressDialog.show(this, "Fetching image", "Go intent service go!");
}

@Override
protected void onResume() {
super.onResume();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ImageIntentService.TRANSACTION_DONE);
registerReceiver(imageReceiver, intentFilter);
}

@Override
protected void onPause() {
super.onPause();
unregisterReceiver(imageReceiver);
}

private BroadcastReceiver imageReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String location = intent.getExtras().getString("imageLocation");
if (location == null || location.length() == 0) {
String failedString = "Failed to download image";
Toast.makeText(context, failedString, Toast.LENGTH_LONG).show();
}

File imageFile = new File(location);
if (!imageFile.exists()) {
pd.dismiss();
String downloadFail = "Unable to download the image";
Toast.makeText(context, downloadFail, Toast.LENGTH_LONG).show();
return;
}
Bitmap image = BitmapFactory.decodeFile(location);
ImageView iv = (ImageView) findViewById(R.id.show_image);
iv.setImageBitmap(image);
pd.dismiss();
}
};

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.my, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}

This is the IntentService class:

package com.example.matt95.myapplication;

import android.app.IntentService;
import android.content.Intent;
import android.os.Environment;
import android.util.Log;
import android.widget.Toast;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class ImageIntentService extends IntentService {

private File cacheDir;
private static final String CACHE_FOLDER = "/myapp/image_cache/";
public static String TRANSACTION_DONE = "com.example.matt95.myapplication.ImageIntentService.TRANSACTION_DONE";

//Constructor method
public ImageIntentService() {
super("ImageIntentService");
}

@Override
public void onCreate() {
super.onCreate();
String tmpLocation = Environment.getExternalStorageDirectory().getPath() + CACHE_FOLDER;
cacheDir = new File(tmpLocation);
if (!cacheDir.exists())
cacheDir.mkdirs();
}

@Override
protected void onHandleIntent(Intent intent) {
if (intent.hasExtra("url")) {
String remoteUrl = intent.getExtras().getString("url");
String imageLocation;
String fileName = remoteUrl.substring(remoteUrl.lastIndexOf(File.separator) + 1);
File tmpImage = new File(cacheDir + "/" + fileName);

if (tmpImage.exists()) {
imageLocation = tmpImage.getAbsolutePath();
notifyFinished(imageLocation, remoteUrl);
stopSelf();
return;
}

try {
URL url = new URL(remoteUrl);
HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
if (httpCon.getResponseCode() != 200)
throw new Exception("Failed to connect");
InputStream is = httpCon.getInputStream();
FileOutputStream fos = new FileOutputStream(tmpImage);
writeStream(is, fos);
fos.flush();
fos.close();
is.close();
imageLocation = tmpImage.getAbsolutePath();
notifyFinished(imageLocation, remoteUrl);
} catch (Exception e) {
Log.e("Service", "Failed!", e);
}
}
}

private void writeStream(InputStream is, OutputStream fos) throws Exception {
byte buffer[] = new byte[80000];
int read = is.read(buffer);
while (read != -1) {
fos.write(buffer, 0, read);
read = is.read(buffer);
}
}

private void notifyFinished(String imageLocation, String remoteUrl) {
Intent i = new Intent(TRANSACTION_DONE);
i.putExtra("imageLocation", imageLocation);
i.putExtra("url", remoteUrl);
ImageIntentService.this.sendBroadcast(i);
}
}

And this is the Manifest file:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.matt95.myapplication" >

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MyActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".ImageIntentService" />
</application>

</manifest>

What am I doing wrong?