title: Android: Can't create handler inside thread that has not called Looper.prepare() Running new threads
body: <p>i'm getting this error which i can't understand why. I'm fairly new to java. What i'm trying to do is start a new thread which will handle all the save image processes. </p>
  
  <p>Error:    </p>
  
  <pre><code> java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
                  at android.os.Handler.&lt;init&gt;(Handler.java:200)
                  at android.os.Handler.&lt;init&gt;(Handler.java:114)
                  at android.app.Dialog.&lt;init&gt;(Dialog.java:108)
                  at android.app.AlertDialog.&lt;init&gt;(AlertDialog.java:125)
                  at android.app.AlertDialog$Builder.create(AlertDialog.java:967)
                  at android.app.AlertDialog$Builder.show(AlertDialog.java:986)
                  at com.example.matts.myapplication.MainActivity$1.handleMessage(MainActivity.java:37)
                  at com.example.matts.myapplication.Saving.run(Saving.java:54)
                  at java.lang.Thread.run(Thread.java:818)
  </code></pre>
  
  <p>Here's my code.</p>
  
  <pre><code>Main:
  
  package com.example..myapplication;
  
  import android.app.Activity;
  import android.app.AlertDialog;
  import android.content.DialogInterface;
  import android.content.Intent;
  import android.graphics.Bitmap;
  import android.graphics.BitmapFactory;
  import android.net.Uri;
  import android.os.Environment;
  import android.os.Handler;
  import android.os.Message;
  import android.provider.MediaStore;
  import android.os.Bundle;
  import android.util.Log;
  import android.view.View;
  import android.widget.ImageView;
  import java.io.File;
  import java.io.FileNotFoundException;
  import java.io.FileOutputStream;
  import java.io.IOException;
  import java.util.Date;
  import java.text.SimpleDateFormat;
  
  
  public class MainActivity extends Activity {
  
      static final int REQUEST_IMAGE_CAPTURE = 1;
      ImageView imageView;
      private static final String TAG = "MyActivity";
      Bitmap image;
  
      Handler goodHandler = new Handler() {
          @Override
          public void handleMessage(Message message) {
              AlertDialog.Builder builder = new AlertDialog.Builder(getApplicationContext());
              builder.setMessage("File Saved").show();
  
          }
  
      };
  
      Handler badHandler = new Handler() {
          @Override
          public void handleMessage(Message message) {
              AlertDialog.Builder builder = new AlertDialog.Builder(getApplicationContext());
              builder.setMessage("File Save failed").show();
  
          }
  
      };
  
  
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          openCamera();
          setContentView(R.layout.activity_main);
          findViewById(R.id.captureImage).bringToFront();
          findViewById(R.id.saveImage).bringToFront();
          imageView = (ImageView) findViewById(R.id.imageView2);
  
      }
  
      protected void onSaveInstanceState(Bundle outState){
          File file = new File(Environment.getExternalStorageDirectory() + File.separator + "TMP.jpg");
          file.delete();
      }
  
      public void openCamera() {
          Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
          File file = new File(Environment.getExternalStorageDirectory() + File.separator + "TMP.jpg");
          takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
          startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
      }
  
  
      protected void onActivityResult(int requestCode, int resultCode, Intent data) {
          //Check that request code matches ours:
          if (requestCode == REQUEST_IMAGE_CAPTURE) {
              //Get our saved file into a bitmap object:
              File file = new File(Environment.getExternalStorageDirectory() + File.separator + "TMP.jpg");
              Bitmap image = decodeSampledBitmapFromFile(file.getAbsolutePath(), 1000, 700);
              imageView.setImageBitmap(image);
          }
      }
  
  // Reduce the amount of dynamic heap used by expanding the JPEG into a memory array that's already scaled to match the size of the destination view
      public static Bitmap decodeSampledBitmapFromFile(String path, int reqWidth, int reqHeight) { // BEST QUALITY MATCH
          //First decode with inJustDecodeBounds=true to check dimensions
          final BitmapFactory.Options options = new BitmapFactory.Options();
          options.inJustDecodeBounds = true;
          BitmapFactory.decodeFile(path, options);
  
          // Calculate inSampleSize, Raw height and width of image
          final int height = options.outHeight;
          final int width = options.outWidth;
          options.inPreferredConfig = Bitmap.Config.RGB_565;
          int inSampleSize = 1;
  
          if (height &gt; reqHeight) {
              inSampleSize = Math.round((float) height / (float) reqHeight);
          }
          int expectedWidth = width / inSampleSize;
  
          if (expectedWidth &gt; reqWidth) {
              //if(Math.round((float)width / (float)reqWidth) &gt; inSampleSize) // If bigger SampSize..
              inSampleSize = Math.round((float) width / (float) reqWidth);
          }
  
          options.inSampleSize = inSampleSize;
  
          // Decode bitmap with inSampleSize set
          options.inJustDecodeBounds = false;
  
          return BitmapFactory.decodeFile(path, options);
      }
  
      public void capture_btn(View v) {
          Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
          File file = new File(Environment.getExternalStorageDirectory() + File.separator + "TMP.jpg");
          takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
          startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
      }
  
  
  
      public void storeImage(Bitmap image) {
          imageView.buildDrawingCache();
          Bitmap bm_img = imageView.getDrawingCache();
          Saving saving = new Saving(bm_img, goodHandler, badHandler);
          Thread thread = new Thread(saving);
          thread.start();
      }
  
      public void save_btn(View v) {
          DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
              @Override
              public void onClick(DialogInterface dialog, int which) {
                  switch (which){
                      case DialogInterface.BUTTON_POSITIVE:
                          storeImage(image);
  
  
                          break;
  
                      case DialogInterface.BUTTON_NEGATIVE:
  
                          break;
                  }
              }
          };
  
          AlertDialog.Builder builder = new AlertDialog.Builder(this);
          builder.setMessage("Are you sure?").setPositiveButton("Yes", dialogClickListener)
                  .setNegativeButton("No", dialogClickListener).show();
  
      } //notification messages
  }
  </code></pre>
  
  <p>Saving: </p>
  
  <pre><code>package com.example..myapplication;
  
  import android.graphics.Bitmap;
  import android.os.Environment;
  import android.os.Message;
  import android.util.Log;
  import android.os.Handler;
  
  
  import java.io.File;
  import java.io.FileNotFoundException;
  import java.io.FileOutputStream;
  import java.io.IOException;
  import java.text.SimpleDateFormat;
  import java.util.Date;
  
  
  public class Saving implements Runnable {
      private Bitmap image;
      private android.os.Handler goodHandler;
      private android.os.Handler badHandler;
      private static final String TAG = "Saving";
  
      public Saving(Bitmap in, Handler hinGood,Handler hinBad) {
          image = in;
          goodHandler = hinGood;
          badHandler = hinBad;
  
  
      }
  
      @Override
      public void run() {
          File file = getOutputMediaFile();
          if (file == null) {
              return;
          }
          try {
              FileOutputStream fos = new FileOutputStream(file);
              image.compress(Bitmap.CompressFormat.PNG, 90, fos);
              fos.close();
          } catch (FileNotFoundException e) {
              Log.d(TAG, "File not found: " + e.getMessage());
              badHandler.handleMessage(new Message());
              return;
          } catch (IOException e) {
              Log.d(TAG, "Error accessing file: " + e.getMessage());
              badHandler.handleMessage(new Message());
              return;
          }
          goodHandler.handleMessage(new Message());
  
  
      }
  
      public File getOutputMediaFile(){
          // To be safe, you should check that the SDCard is mounted
          // using Environment.getExternalStorageState() before doing this.
          File mediaStorageDir = new File(Environment.getExternalStorageDirectory()
                  + "/Pictures/Wiki_camera"
                  + "/Photos");
  
          // This location works best if you want the created images to be shared
          // between applications and persist after your app has been uninstalled.
  
          // Create the storage directory if it does not exist
          if (! mediaStorageDir.exists()){
              if (! mediaStorageDir.mkdirs()){
                  return null;
              }
          }
          // Create a media file name
          String timeStamp = new SimpleDateFormat("ddMMyyyy_HHmm").format(new Date());
          File mediaFile;
          String mImageName="camera_wiki"+ timeStamp +".jpg";
          mediaFile = new File(mediaStorageDir.getPath() + File.separator + mImageName);
          return mediaFile;
      }
  
  }
  </code></pre>
  
  <p>I've added whole of the main class and the saving class. </p>