2016-11-19 4 views
0

나는 이미지 캡처 및 이미지에 제목을 추가하는 안드로이드 애플 리케이션을 만들었습니다. 응용 프로그램 난 모바일의 카메라에서 사용할 때 제대로 작동하지만, 내가 카메라를 다시 사용하는 경우 응용 프로그램이 오류 java.lang.outofmemory 내 코드와 함께 추락하고있다는치명적인 예외 java.lang.outofmemory 백 카메라를 사용하는 경우

public class MainActivity extends AppCompatActivity { 

private ImageView imageResult; 
Bitmap processedBitmap; 
String photoName; 
Uri source1; 
private String pictureImagePath = ""; 
File imgFile; 

/** 
* ATTENTION: This was auto-generated to implement the App Indexing API. 
* See https://g.co/AppIndexing/AndroidStudio for more information. 
*/ 
private GoogleApiClient client; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    imageResult = (ImageView) this.findViewById(R.id.imageView1); 
    Button takePicture = (Button) this.findViewById(R.id.btnTakePic); 
    Button renamePicture = (Button) this.findViewById(R.id.btnRename); 
    Button savePicture = (Button) this.findViewById(R.id.btnSave); 
    final File myDir=new File("/sdcard/saved_images"); 
    myDir.mkdirs(); 
    File myDirTemp = new File("/sdcard/saved_images/Temp"); 
    myDirTemp.mkdirs(); 

    takePicture.setOnClickListener(new View.OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); 
      String imageFileName = timeStamp + ".jpg"; 
      File storageDir = new File("/sdcard/saved_images/Temp"); 
      pictureImagePath = storageDir.getAbsolutePath() + "/" + imageFileName; 
      File file = new File(pictureImagePath); 
      Uri outputFileUri = Uri.fromFile(file); 
      Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); 
      cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri); 
      startActivityForResult(cameraIntent, 1); 


     } 
    }); 
    renamePicture.setOnClickListener(new View.OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      if(source1!=null){ 
       AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this); 
       final EditText input = new EditText(MainActivity.this); 
       input.setInputType(InputType.TYPE_CLASS_NUMBER); 
       LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
         LinearLayout.LayoutParams.MATCH_PARENT, 
         LinearLayout.LayoutParams.MATCH_PARENT); 
       input.setLayoutParams(lp); 
       dialog.setView(input); 
       dialog.setCancelable(false); 
       dialog.setTitle("Rename Photo"); 
       dialog.setMessage("Enter Photo Name"); 
       dialog.setPositiveButton("Save", null); 
       dialog.setNegativeButton("cancel", null); 

       final AlertDialog alertdialog = dialog.create(); 
       alertdialog.setOnShowListener(new DialogInterface.OnShowListener() { 

        @Override 
        public void onShow(DialogInterface dialog) { 
         // TODO Auto-generated method stub 
         Button b = alertdialog.getButton(AlertDialog.BUTTON_POSITIVE); 
         Button c = alertdialog.getButton(AlertDialog.BUTTON_NEGATIVE); 

         b.setOnClickListener(new View.OnClickListener() { 

          @Override 
          public void onClick(View v) { 
           // TODO Auto-generated method stub 
           String SpinName = input.getText().toString(); 
           if(SpinName.length()==0){ 
            Toast.makeText(MainActivity.this, "Enter Photo Name", Toast.LENGTH_LONG).show(); 
           }else{ 
            photoName = input.getText().toString(); 
            processedBitmap = ProcessingBitmap(); 
            if(processedBitmap != null){ 
             imageResult.setImageBitmap(processedBitmap); 
            } 
           } 
           alertdialog.dismiss(); 

          } 
         }); 
         c.setOnClickListener(new View.OnClickListener() { 

          @Override 
          public void onClick(View v) { 
           // TODO Auto-generated method stub 
           alertdialog.dismiss(); 
          } 
         }); 
        } 
       });alertdialog.show();} 
      else{ 
       Toast.makeText(MainActivity.this, "Take Image First", Toast.LENGTH_LONG).show(); 
      } 
     } 
    }); 


    savePicture.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      if(source1!=null){ 
      String fname = photoName +".jpg"; 
      File file = new File (myDir, fname); 
      if (file.exists()) file.delete(); 
      try { 
       FileOutputStream out = new FileOutputStream(file); 
       processedBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out); 
       out.flush(); 
       out.close(); 

       AlertDialog.Builder aldialog = (new AlertDialog.Builder(MainActivity.this)); 
       aldialog.setTitle("saved"); 
       aldialog.setMessage("Image Saved Successfully"); 
       aldialog.setPositiveButton("OK", new DialogInterface.OnClickListener(){ 
        @Override 
        public void onClick(DialogInterface dialog, int which) { 
         imageResult.setImageResource(0); 
         source1 = null; 
        } 
       });aldialog.show(); 

      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
     else{ 
      Toast.makeText(MainActivity.this, "Take Image First", Toast.LENGTH_LONG).show(); 
     } 
     } 
    }); 
} 

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

    if (requestCode == 1) { 
     imgFile = new File(pictureImagePath); 
     if(imgFile.exists()){ 
      source1 = Uri.fromFile(imgFile); 
      Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath()); 
      imageResult.setImageBitmap(myBitmap); 


     } 
    } 

} 

private Bitmap ProcessingBitmap() { 
    Bitmap bm1 = null; 
    Bitmap newBitmap = null; 
    try{ 
     bm1 = BitmapFactory.decodeStream(getContentResolver().openInputStream(Uri.fromFile(imgFile))); 

     Bitmap.Config config = bm1.getConfig(); 
     if(config==null){ 
      config = Bitmap.Config.ARGB_8888; 
     } 
     newBitmap = Bitmap.createBitmap(bm1.getWidth(), bm1.getHeight(),config); 
     Canvas newCanvas = new Canvas(newBitmap); 
     newCanvas.drawBitmap(bm1,0,0,null); 

     if(photoName!= null){ 
      Paint paintText = new Paint(Paint.ANTI_ALIAS_FLAG); 
      paintText.setColor(Color.WHITE); 
      paintText.setTextSize(120); 
      paintText.setShadowLayer(10f,10f,10f, Color.BLACK); 
      Rect rectText = new Rect(); 
      paintText.getTextBounds(photoName, 0, photoName.length(), rectText); 
      newCanvas.drawText(photoName, 0, bm1.getHeight()- rectText.height(), paintText); 
      //newCanvas.drawText(photoName,bm1.getWidth()-rectText.left,bm1.getWidth()-rectText.top, paintText); 


      Toast.makeText(MainActivity.this, "done", Toast.LENGTH_LONG).show();} 
     else{ 
      Toast.makeText(MainActivity.this, "undone", Toast.LENGTH_LONG).show();} 
    } catch (FileNotFoundException e) { 
     e.printStackTrace(); 
    } 
    return newBitmap; 
} 
} 

몇 가지 제안을 알려주세요 여기에있다. 여기 예외 로그

E/AndroidRuntime : 치명적인 예외 : 주요 프로세스 : com.surveyphotoapp, PID : 24765 java.lang.OutOfMemoryError와 android.graphics.Bitmap.nativeCreate (기본 방법) 에서 android.graphics에서 .Bitmap.createBitmap (Bitmap.java:822) android.graphics.Bitmap.createBitmap의 (Bitmap.java:799) android.graphics.Bitmap.createBitmap (Bitmap.java:766)의 at com.surveyphotoapp.MainActivity .ProcessingBitmap (MainActivity.java:214) at com.surveyphotoapp .MainActivity.access $ 100 (MainActivity.java:44) at com.surveyphotoapp.MainActivity $ 2 $ 1 $ 1.onClick (MainActivity.java:127) at android.view.View.performClick (View.java:4444) at android .view.View $ PerformClick.run (View.java:18440) (android.os.Handler.handleCallback (Handler.java:733) at android.os.Handler.dispatchMessage (Handler.java:95) at android .os.Looper.loop (Looper.java:136) android.app.ActivityThread.main (ActivityThread.java:5052) at java.lang.reflect.Method.invokeNative (네이티브 메소드) at java.lang. reflect.Method.invoke (Method.java:515) at com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run (ZygoteInit.java:796) at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:612) at dalvik.system.NativeStart. main (기본 방법)

+0

로그를 추가 할 수 있습니까? – emrekose26

+0

로그로 내 질문을 업데이트했습니다. –

답변

0

후면 카메라의 이미지 해상도가 전면 카메라보다 높습니다. 따라서 특히 작은 VM 힙 크기를 가진 장치에서 OutOfMemoryError를 사용하면 바이트 스트림에서 직접 비트 맵을 만들 수 있습니다.

작은 VM 힙 크기에서 오류가 발생하지 않도록하려면 비트 맵을 디코딩하는 동안 OutOfMemoryError를 잡아낼 수 있습니다. 그런 경우 이미지 크기를 줄인 다음 다시 시도하십시오.

public static Bitmap getBitmapFromStream(Context context, InputStream istr) { 
    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 
    Display display = wm.getDefaultDisplay(); 
    final int REQUIRED_SIZE = display.getWidth(); 

    istr.mark(Integer.MAX_VALUE); 
    BitmapFactory.Options o = new BitmapFactory.Options(); 
    o.inJustDecodeBounds = true; 
    BitmapFactory.decodeStream(istr, null, o); 
    int width_tmp = o.outWidth, height_tmp = o.outHeight; 
    int scale = 1; 
    while (true){ 
     if (width_tmp/2 < REQUIRED_SIZE) 
      break; 
     width_tmp /= 2; 
     height_tmp /= 2; 
     scale *= 2; 
    } 

    while (true) { 
     try { 
      istr.reset(); 
      o = new BitmapFactory.Options(); 
      o.inSampleSize = scale; 
      return BitmapFactory.decodeStream(istr, null, o); 
     } catch (OutOfMemoryError ex) { 
      scale *= 2; 
      if (scale >= 32) { 
       // Failed 
       return null; 
      } 
     } catch (IOException ex) { 
      ex.printStackTrace(); 
      return null; 
     } 
    } 
} 
+0

이미지 위로 텍스트를 추가하려고 할 때 오류가 발생합니다. 이름 바꾸기 버튼을 클릭하십시오. –

+0

앱에 bm1을 만들 때 비트 맵을 저장할 메모리가 충분하지만 메모리가 충분하지 않은 것 같습니다. 한 번에 같은 크기의 두 비트 맵을 유지하십시오 (두 번째 비트 맵 작성은 OutOfMemoryError와 함께 실패합니다). 첫 번째 비트 맵의 ​​복사본을 만들기 전에 크기를 줄이는 것이 좋습니다. 또한,이 제안을 따르십시오 : [링크] (http://stackoverflow.com/questions/14232440/how-to-increase-android-virtual-device-max-heap-size) – vmayorow

+0

그것의 모든 시간을 작동하지만. 감사합니다 –