Android - AsyncTask致命异常

问题描述:

我从javaCameraView的位图中加载图像。这一个发送到异步任务,以便将其发送到PHP文件。在第一秒内没有问题。 在这段时间之后,我遇到了线程问题,但是我找不到解决方案。 这是logcat的:Android - AsyncTask致命异常

07-25 16:36:29.492: E/AndroidRuntime(17507): FATAL EXCEPTION: AsyncTask #5 
    07-25 16:36:29.492: E/AndroidRuntime(17507): java.lang.RuntimeException: An error occured while executing doInBackground() 
    07-25 16:36:29.492: E/AndroidRuntime(17507): at android.os.AsyncTask$3.done(AsyncTask.java:299) 
    07-25 16:36:29.492: E/AndroidRuntime(17507): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273) 
    07-25 16:36:29.492: E/AndroidRuntime(17507): at java.util.concurrent.FutureTask.setException(FutureTask.java:124) 
    07-25 16:36:29.492: E/AndroidRuntime(17507): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307) 
    07-25 16:36:29.492: E/AndroidRuntime(17507): at java.util.concurrent.FutureTask.run(FutureTask.java:137) 
    07-25 16:36:29.492: E/AndroidRuntime(17507): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230) 
    07-25 16:36:29.492: E/AndroidRuntime(17507): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076) 
    07-25 16:36:29.492: E/AndroidRuntime(17507): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569) 
    07-25 16:36:29.492: E/AndroidRuntime(17507): at java.lang.Thread.run(Thread.java:856) 
    07-25 16:36:29.492: E/AndroidRuntime(17507): Caused by: java.lang.OutOfMemoryError 
    07-25 16:36:29.492: E/AndroidRuntime(17507): at java.lang.String.<init>(String.java:375) 
    07-25 16:36:29.492: E/AndroidRuntime(17507): at java.lang.String.<init>(String.java:238) 
    07-25 16:36:29.492: E/AndroidRuntime(17507): at android.util.Base64.encodeToString(Base64.java:456) 
    07-25 16:36:29.492: E/AndroidRuntime(17507): at com.example.objectDetect.SendData.getStringFromBitmap(SendData.java:186) 
    07-25 16:36:29.492: E/AndroidRuntime(17507): at com.example.objectDetect.SendData.doInBackground(SendData.java:63) 
    07-25 16:36:29.492: E/AndroidRuntime(17507): at com.example.objectDetect.SendData.doInBackground(SendData.java:1) 
    07-25 16:36:29.492: E/AndroidRuntime(17507): at android.os.AsyncTask$2.call(AsyncTask.java:287) 
    07-25 16:36:29.492: E/AndroidRuntime(17507): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305) 
    07-25 16:36:29.492: E/AndroidRuntime(17507): ... 5 more 

我认为这个问题是在这个功能,但我不知道为什么:

private String getStringFromBitmap(Bitmap bitmapPicture) 
{ 
    if(!bitmapPicture.isRecycled()) 
    { 
     final int COMPRESSION_QUALITY = 100; 
     String encodedImage; 
     ByteArrayOutputStream byteArrayBitmapStream = new ByteArrayOutputStream(); 
     bitmapPicture.compress(Bitmap.CompressFormat.PNG, COMPRESSION_QUALITY, byteArrayBitmapStream); 
     byte[] b = byteArrayBitmapStream.toByteArray(); 
     encodedImage = Base64.encodeToString(b, Base64.DEFAULT); 
     return encodedImage; 
    } 
    else 
    { 
     return null; 
    } 
} 

很多测试之后,我有不同的logcat但它总是记忆问题。我在运行函数的线程中创建一个位图。

Herebelow的logcat的:

07-26 09:42:50.491: E/AndroidRuntime(31291): FATAL EXCEPTION: Thread-27487 
    07-26 09:42:50.491: E/AndroidRuntime(31291): java.lang.OutOfMemoryError 
    07-26 09:42:50.491: E/AndroidRuntime(31291): at android.graphics.Bitmap.nativeCreate(Native Method) 
    07-26 09:42:50.491: E/AndroidRuntime(31291): at android.graphics.Bitmap.createBitmap(Bitmap.java:640) 
    07-26 09:42:50.491: E/AndroidRuntime(31291): at android.graphics.Bitmap.createBitmap(Bitmap.java:620) 
    07-26 09:42:50.491: E/AndroidRuntime(31291): at com.example.objectDetection.objectDetectionView$1.run(objectDetectionView.java:197) 

预先感谢您的帮助。

+4

你需要缩小你的位图。 http://developer.android.com/training/displaying-bitmaps/load-bitmap.html – Raghunandan

+0

也许,但是这个问题出现在测试的1到2分钟左右...... – user2619284

+2

是base-64编码真的有必要吗?使用二进制数据将更有效率......这是消耗太多内存的操作 – CSmith

下面的代码是我想出来的,以避免加载位图时出现内存不足错误。

private Bitmap loadImageFromNetwork(String urlToUse) { 
    Bitmap img = null; 
    URL url; 
    try { 
     //A uniform resource locator aka the place where the data is  
     //located 
     url = new URL(urlToUse); 
     //Opens an HTTPUrlConnection and downloads the input stream into a 
     //Bitmap 
     final BitmapFactory.Options options = new BitmapFactory.Options(); 
     // Prevents loading of image into memory and just ascertains bounds and memory footprint 
     options.inJustDecodeBounds = true; 

     BitmapFactory.decodeStream(url.openStream(),null,options); // gather image data 
     options.inSampleSize = Photo.calculateInSampleSize(options, 
       Photo.THUMBNAIL_WIDTH, Photo.THUMBNAIL_HEIGHT); 
     options.inJustDecodeBounds = false; 
     img = BitmapFactory.decodeStream(url.openStream(),null,options); 

    } catch (MalformedURLException e) { 
     Log.i("PAR", "URL is malformed"); 
     e.printStackTrace(); 
    } catch (IOException e) { 
     Log.i("PAR", "Failed to decode Bitmap"); 
     e.printStackTrace(); 
    } 

    return img; 

} // end load function 


public static int calculateInSampleSize(
    BitmapFactory.Options options, int reqWidth, int reqHeight) { 
    // Raw height and width of image 
    final int height = options.outHeight; 
    final int width = options.outWidth; 
    int inSampleSize = 1; 

    if (height > reqHeight || width > reqWidth) { 
     if (width > height) { 
      inSampleSize = Math.round((float)height/(float)reqHeight); 
     } else { 
      inSampleSize = Math.round((float)width/(float)reqWidth); 
     } // end if 
    } // end out if 
    return inSampleSize; 
} 

这里确定的关键是最初的负载不包括整个图像。 JDeveloDeBoundsBounds中的标志被设置为true,其确实如其听起来那样。它只解码边界,以便您可以提前确定图像是否太大。我的建议是确定边界和其他相关数据,然后在加载所有图像之前进行调整。对于这个例子,我将大图片转换为缩略图。

使用此技术应在缩小图像大小之前缩小它们。我想这种折衷是你在减少负载上的图像,这可能意味着质量较低。但是,如果你的内存不足,这可能是一个可行的选择,如果你愿意缩小图像。

+0

问题是位图是从javacamera视图加载的。所以我加载一个矩阵。 – user2619284

+0

您应该在问题中包含有关您的问题的更多信息。提供的内容很难提供一个很好的答案。 –

+0

我从javaCameraView的位图中加载图像。这一个发送到异步任务,以便将其发送到PHP文件。 – user2619284