2015-05-02 33 views
1

我收到了這個錯誤,我不明白爲什麼。我對Java相當陌生。我想要做的是啓動一個新的線程,它將處理所有的保存圖像過程。Android:無法在未調用Looper.prepare()的線程中創建處理程序運行新線程

錯誤:

java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() 
       at android.os.Handler.<init>(Handler.java:200) 
       at android.os.Handler.<init>(Handler.java:114) 
       at android.app.Dialog.<init>(Dialog.java:108) 
       at android.app.AlertDialog.<init>(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) 

這裏是我的代碼。

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 > reqHeight) { 
      inSampleSize = Math.round((float) height/(float) reqHeight); 
     } 
     int expectedWidth = width/inSampleSize; 

     if (expectedWidth > reqWidth) { 
      //if(Math.round((float)width/(float)reqWidth) > 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 
} 

保存:

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; 
    } 

} 

我已經添加了整個主類和儲蓄類的。

+0

請發送'storeImage()'代碼。 – pathfinderelite

+0

完成,添加到問題。 – smither123

+0

「goodHandler」和「badHandler」在哪裏定義? – pathfinderelite

回答

1

的問題是,你在呼喚handleMessage()代替sendMessage(),這裏

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()); 

結果,下面的不叫UI線程上

AlertDialog.Builder builder = new AlertDialog.Builder(getApplicationContext()); 
builder.setMessage("File Saved").show(); 

並因此引發異常。

+0

謝謝,它工作。我現在有另一個錯誤「android.view.WindowManager $ BadTokenException:無法添加窗口 - 標記null不適用於應用程序」 – smither123

+0

看看[這個](http://stackoverflow.com/questions/2634991/android -1-6-Android的視圖windowmanagerbadtokenexception-無法對插件窗口)。簡而言之,它表示使用'getContext()'(或'this')而不是'getApplicationContext()'。如果這沒有幫助,您可以發佈一個單獨的SO問題,因爲這是一個單獨的錯誤。一定要包含代碼和堆棧跟蹤。 – pathfinderelite

0

嘗試

runOnUiThread (new Thread(new Runnable() { 
     public void run() { 
       storeImage(image); 
     } 
    })); 
相關問題