В моем приложении у меня есть действие, которое действует как предварительный просмотр камеры.Я использую SurfaceView, растянутый по всему экрану, вместе с кучей элементов, наложенных поверх него, но ничего сложного.Это действие может запускать другие действия, которые затем возвращаются к предварительному просмотру камеры.
Я очень тщательно очищал ресурсы, перерабатывал растровые изображения, избегал утечек памяти и т. Д. Я могу запустить это приложение и проверить егокак сумасшедший, но когда мой телефон был включен некоторое время и другие приложения находятся в памяти, я получаю тихие отключения при возобновлении или создании действия, которое содержит предварительный просмотр камеры.Обычный тестовый сценарий для воспроизведения аварии - это использование приложения, создание фотографий (запускающих обработку), запуск дополнительных действий и т. Д. Снова и снова.Выйдите из приложения, запустите что-нибудь ресурсоемкое или графическое, а затем возобновите работу моего приложения.
Вот некоторые выходные данные logcat во время сбоя:
03-29 14:20:02.109: ERROR/dalvikvm(6368): externalAllocPossible(): footprint 2756592 + extAlloc 15831356 + n 8640000 >= max 22409232 (space for 3821284)
03-29 14:20:02.109: ERROR/dalvikvm-heap(6368): 8640000-byte external allocation too large for this process.
03-29 14:20:02.109: ERROR/dalvikvm(6368): Out of memory: Heap Size=3835KB, Allocated=2835KB, Bitmap Size=15460KB, Limit=21884KB
03-29 14:20:02.109: ERROR/dalvikvm(6368): Trim info: Footprint=5383KB, Allowed Footprint=5383KB, Trimmed=1548KB
03-29 14:20:02.109: ERROR/GraphicsJNI(6368): VM won't let us allocate 8640000 bytes
Моя активностьведение журнала на каждом этапе, так что это происходит в Activity.onCreate между вызовом super.onCreate и настройкой представления контекста для моего макета xml.Моей первой мыслью было, что процесс получения SurfaceHolder или чего-либо, что происходит в методах SurfaceHolder, может оказаться слишком сложным в ситуации с нехваткой памяти, но это происходит гораздо раньше.Похоже, что это происходит в setContentView при анализе моего XML-макета и создании объектов View.
Код предварительного просмотра моей камеры взят из примеров, которые я нашел в книгах и статьях, поэтому мне интересно, есть лидополнительную очистку мне нужно сделать в SurfaceDestroyed?Должен ли я попытаться запустить сборку мусора в этот момент?Причина такого мышления заключается в том, что в системе достаточно памяти для запуска приложения в условиях, когда в памяти меньше приложений.Это либо связано с тем, что мое собственное приложение недостаточно очищается, либо система не в состоянии восстановить память достаточно быстро для моего приложения.Я не понимаю, почему во время setContentView он пытается выделить столько новой памяти.
Вот мой поверхностный код обратного вызова и перефразировка того, что происходит в действии
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.camera_preview);
// crash occurs here
// ...other stuff
initControls();
}
private void initControls()
{
previewHolder = preview.getHolder();
previewHolder.addCallback(surfaceCallback);
previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
// ...other stuff
}
SurfaceHolder.Callback surfaceCallback = new Callback() {
public void surfaceDestroyed(SurfaceHolder holder) {
Log.d(ApplicationEx.LogTag, "surfaceDestroyed");
camera.stopPreview();
camera.release();
camera = null;
isPreviewRunning = false;
}
public void surfaceCreated(SurfaceHolder holder) {
Log.d(ApplicationEx.LogTag, "surfaceCreated");
camera = Camera.open();
try
{
camera.setPreviewDisplay(previewHolder);
}
catch(Throwable t)
{
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
Log.d(ApplicationEx.LogTag, "surfaceChanged");
if (isPreviewRunning)
{
Log.d(ApplicationEx.LogTag, "preview is running, stop preview");
camera.stopPreview();
isPreviewRunning = false;
}
Camera.Parameters parameters = camera.getParameters();
setPreviewAndPictureSize(parameters, width, height);
parameters.setPictureFormat(PixelFormat.JPEG);
parameters.setJpegQuality(85);
camera.setParameters(parameters);
camera.startPreview();
isPreviewRunning = true;
Log.d(ApplicationEx.LogTag, "end surfaceChanged");
}
};