AzoftБлогКак исправить баг в SQLite 3.5.9 на Android 2.1

Как исправить баг в SQLite 3.5.9 на Android 2.1

Александр Акимов Октябрь 17, 2012

Занимаясь разработкой Android-приложений, мы часто оказываемся в ситуации, когда заказчики устанавливают довольно низкий порог поддерживаемых версий операционной системы. Так недавно одна компания попросила, чтобы ее приложение поддерживалось на устройствах с Android 2.1 (API7) и выше. В свое время эта версия была прорывом, но в ходе проекта обнаружилась проблема: во встроенной SQLite 3.5.9 оказался документированный «плавающий» баг. Чаще он проявлялся при активной записи в базу, но можно было его поймать и при чтении. SQLite падал с ошибкой  «Disk image malformed» (Нарушена целостность базы на диске), вся база данных становится недоступной и получить из нее какую-либо информацию стандартными путями становилось невозможно. Обычно в таких случаях помогает Google, но Google молчал, и нам пришлось экспериментировать.

График. Официальная статистика Google с процентным соотношением используемых версий Android.

Итак, что делать, если вы наткнулись на ту же проблему. Достаточно добавить стандартную архитектуру для провайдера базы данных в ваше приложение.

1. Реализацию SQLiteOpenHelper оставляем без изменений. Она нам пригодится.

2. Применяя android.content.ContentProvider, создаем провайдер. Все сводится к реализации методов insert, update, delete и query. Они однотипны, нужно проанализировать URI и вызывать реализацию SQLiteOpenHelper.  Мы еще добавили централизованную работу с ошибками: SQLiteException и NullPointerException — их стоит обрабатывать, так как обе выпадают в случае выхода SD-карты устройства из строя или ее переполнении.

3. Добавляем в AndroidManifest.xml строчки:

<provider android:name="com.somecompany.database.DatabaseProvider" android:authorities="com.somecompany" android:exported="false">

Последнее значение android:exported обеспечивает невидимость данных из соседних приложений.

4. Для удобства всю логику по формированию URI и запросов к реализации ContentProvider лучше вынести еще на уровень выше. Провайдер создается самой платформой и с этого слоя реализации уже работает как черный ящик:

context.getContentResolver().insert( "content://" + "com.somecompany" + "someTable", contentValues);

За техническими деталями организации ContentProvider и доступа к базе данных лучше заглянуть на developer.android.com. Официальное руководство довольно доходчивое./p>

Со своей стороны хочу добавить, что принятые меры, а именно использование database провайдера в приложении, дало положительный результат, и проект был успешно завершен.

Комментарии

комментарии



Content created by Alexander Ak