Android 应用程序中的预加载数据库损坏问题

发布于 2024-12-07 07:34:55 字数 4015 浏览 0 评论 0原文

我有一个 Android 应用程序,首先在异步任务中将大型数据库下载到 SD 卡(略多于 50MB)。下载代码如下。

HttpURLConnection conexion = (HttpURLConnection) url.openConnection();
if(filePath.exists() && filePath.length() > 10000.00)
{
    downloaded = (int) filePath.length();
    conexion.setRequestProperty("Range", "bytes=" + (filePath.length()) + "-");
}
else
    conexion.setRequestProperty("Range", "bytes=" + downloaded + "-");

conexion.setDoInput(true);
conexion.setDoOutput(true);
conexion.setUseCaches(false);
conexion.connect();

...

try {
    totalFileLength = lengthOfFile + downloaded;
    progressDialog.setMax(lengthOfFile + downloaded);
    // downlod the file
    input = new BufferedInputStream(conexion.getInputStream());
    output = (downloaded==0)? new FileOutputStream(filePath): new FileOutputStream(filePath,true);
    bout = new BufferedOutputStream(output, 1024);

    byte data[] = new byte[1024];

    while ((count = input.read(data, 0, 1024)) >= 0 && running) {
        downloaded += count;
        // publishing the progress....
        //onProgressUpdate((int)(downloaded*100/lengthOfFile));
        progressDialog.setProgress(downloaded);
        bout.write(data, 0, count);
    }
} catch (Exception e) {
    ...
} finally {
    try {
        input.close();
        bout.flush();
        bout.close();
    } catch(IOException e) {
        ...
    }
}

完全下载文件后,我打开数据库并向其中添加一个表。

try {
    myDbHelper.myDataBase.execSQL("CREATE TABLE IF NOT EXISTS FAVORITES (_id integer primary key autoincrement, MushroomID INTEGER)");
    success = true;
} catch (SQLException sqle) {
    throw sqle;
}

现在,这段代码在我运行它的每台设备上都运行得很好,但我的一些用户在 execSQL 行上遇到了这个错误。似乎它不能单独在 Samsung Galaxy SII 上运行(没有任何其他手机出现此错误的投诉和后续堆栈跟踪),但我不完全确定它只是这款手机。

java.lang.RuntimeException: Unable to start activity ComponentInfo{net.daleroy.fungifieldguide/net.daleroy.fungifieldguide.activities.FungiFieldGuide}: android.database.sqlite.SQLiteDatabaseCorruptException: database disk image is malformed: CREATE TABLE IF NOT EXISTS FAVORITES (_id integer primary key autoincrement, MushroomID INTEGER)
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1651)
       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1667)
       at android.app.ActivityThread.access$1500(ActivityThread.java:117)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:935)
       at android.os.Handler.dispatchMessage(Handler.java:99)
       at android.os.Looper.loop(Looper.java:130)
       at android.app.ActivityThread.main(ActivityThread.java:3691)
       at java.lang.reflect.Method.invokeNative(Native Method)
       at java.lang.reflect.Method.invoke(Method.java:507)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:907)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:665)
       at dalvik.system.NativeStart.main(Native Method)
Caused by: android.database.sqlite.SQLiteDatabaseCorruptException: database disk image is malformed: CREATE TABLE IF NOT EXISTS FAVORITES (_id integer primary key autoincrement, MushroomID INTEGER)
       at android.database.sqlite.SQLiteDatabase.native_execSQL(Native Method)
       at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1904)
       at net.daleroy.fungifieldguide.services.MushroomService.MakeFavoriteTable(MushroomService.java:118)
       at net.daleroy.fungifieldguide.services.MushroomService.OpenDB(MushroomService.java:64)
       at net.daleroy.fungifieldguide.activities.FungiFieldGuide.onCreate(FungiFieldGuide.java:73)
       at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1615)

我收到了使用 sgs2 的用户下载的数据库副本,并且该文件的校验和已关闭。当我使用 sqlite 管理器(firefox 插件)打开文件时,我也看不到文件中的任何数据或数据结构。我让他直接下载数据库的副本并将其放在他的数据文件夹中,应用程序运行良好。所以问题出在下载过程中的某个地方。

I have an android application that begins by downloading a large database to the sdcard (a little over 50mb) in an asynctask. The download code is as follows.

HttpURLConnection conexion = (HttpURLConnection) url.openConnection();
if(filePath.exists() && filePath.length() > 10000.00)
{
    downloaded = (int) filePath.length();
    conexion.setRequestProperty("Range", "bytes=" + (filePath.length()) + "-");
}
else
    conexion.setRequestProperty("Range", "bytes=" + downloaded + "-");

conexion.setDoInput(true);
conexion.setDoOutput(true);
conexion.setUseCaches(false);
conexion.connect();

...

try {
    totalFileLength = lengthOfFile + downloaded;
    progressDialog.setMax(lengthOfFile + downloaded);
    // downlod the file
    input = new BufferedInputStream(conexion.getInputStream());
    output = (downloaded==0)? new FileOutputStream(filePath): new FileOutputStream(filePath,true);
    bout = new BufferedOutputStream(output, 1024);

    byte data[] = new byte[1024];

    while ((count = input.read(data, 0, 1024)) >= 0 && running) {
        downloaded += count;
        // publishing the progress....
        //onProgressUpdate((int)(downloaded*100/lengthOfFile));
        progressDialog.setProgress(downloaded);
        bout.write(data, 0, count);
    }
} catch (Exception e) {
    ...
} finally {
    try {
        input.close();
        bout.flush();
        bout.close();
    } catch(IOException e) {
        ...
    }
}

After downloading the file completely I open the database and add a table to it.

try {
    myDbHelper.myDataBase.execSQL("CREATE TABLE IF NOT EXISTS FAVORITES (_id integer primary key autoincrement, MushroomID INTEGER)");
    success = true;
} catch (SQLException sqle) {
    throw sqle;
}

Now, this code works wonderfully on every device I run it on, but several of my users are getting this error on the execSQL line. It seems like it is not working on the Samsung Galaxy SII alone (there hasn't been a complaint and subsequent stacktrace with this error with any other phone) but I'm not entirely sure its just this phone.

java.lang.RuntimeException: Unable to start activity ComponentInfo{net.daleroy.fungifieldguide/net.daleroy.fungifieldguide.activities.FungiFieldGuide}: android.database.sqlite.SQLiteDatabaseCorruptException: database disk image is malformed: CREATE TABLE IF NOT EXISTS FAVORITES (_id integer primary key autoincrement, MushroomID INTEGER)
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1651)
       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1667)
       at android.app.ActivityThread.access$1500(ActivityThread.java:117)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:935)
       at android.os.Handler.dispatchMessage(Handler.java:99)
       at android.os.Looper.loop(Looper.java:130)
       at android.app.ActivityThread.main(ActivityThread.java:3691)
       at java.lang.reflect.Method.invokeNative(Native Method)
       at java.lang.reflect.Method.invoke(Method.java:507)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:907)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:665)
       at dalvik.system.NativeStart.main(Native Method)
Caused by: android.database.sqlite.SQLiteDatabaseCorruptException: database disk image is malformed: CREATE TABLE IF NOT EXISTS FAVORITES (_id integer primary key autoincrement, MushroomID INTEGER)
       at android.database.sqlite.SQLiteDatabase.native_execSQL(Native Method)
       at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1904)
       at net.daleroy.fungifieldguide.services.MushroomService.MakeFavoriteTable(MushroomService.java:118)
       at net.daleroy.fungifieldguide.services.MushroomService.OpenDB(MushroomService.java:64)
       at net.daleroy.fungifieldguide.activities.FungiFieldGuide.onCreate(FungiFieldGuide.java:73)
       at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1615)

I've received a copy of the database downloaded from a user with a sgs2 and the checksum of the file is off. I also cannot see any data or data structure in the file when I open with sqlite manager (firefox plugin). I let him download a copy of the database directly and place it in his data folder and the application works fine. So the problem is somewhere in the download process.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

迷荒 2024-12-14 07:34:55

从 API 级别 9 (Android 2.3) 开始,您可以使用 DownloadManager来处理长时间运行的 HTTP 下载:

下载管理器是一个处理长时间运行的系统服务
HTTP 下载。客户端可以请求将 URI 下载到
特定的目标文件。下载管理器将执行
在后台下载,处理 HTTP 交互
失败后或连接更改后重试下载以及
系统重新启动。

以下是演示 DownloadManager 用法的示例项目:Android DownloadManager 示例< /a>.

我认为您甚至可以尝试将 DownloadManager 向后移植到以前的 Android 版本(如果您需要支持它们)。其源代码可以在这里找到:DownloadManager.java

Starting from the API level 9 (Android 2.3) you can use DownloadManager to handle long-running HTTP downloads:

The download manager is a system service that handles long-running
HTTP downloads. Clients may request that a URI be downloaded to a
particular destination file. The download manager will conduct the
download in the background, taking care of HTTP interactions and
retrying downloads after failures or across connectivity changes and
system reboots.

Here is the example project which demonstrates DownloadManager usage: Android DownloadManager Example.

I think you can even try to backport DownloadManager to the previous Android versions (if you need to support them). Its source code can be found here: DownloadManager.java

愿与i 2024-12-14 07:34:55

你在你的输出流上调用flush和close吗?就像这样:

while ((count = input.read(data, 0, 1024)) >= 0 && running) {
    downloaded += count;
    progressDialog.setProgress(downloaded);
    bout.write(data, 0, count);
}
bout.flush();
bout.close();

如果没有,我会从那开始。我下载了一个具有类似代码的视频,发现对于某些设备和某些不调用刷新的视频会损坏并使其无法播放

are you calling flush and close on your outputstream? Like this:

while ((count = input.read(data, 0, 1024)) >= 0 && running) {
    downloaded += count;
    progressDialog.setProgress(downloaded);
    bout.write(data, 0, count);
}
bout.flush();
bout.close();

If not I would start with that. I downloaded a video with similar code and found that for some devices and some videos not calling flush was corrupting and making it unplayable

春庭雪 2024-12-14 07:34:55

这是另一个讨论这种数据库损坏的问题 Android - 数据库磁盘映像格式错误< /a>.

如果在这种状态下您无法修复数据库,也许您可​​以在出现此错误时尝试再次下载(假设此问题很少见,并且再次下载数据库可以解决问题)。

Here is another question that talks about this kind of database corruption Android - database disk image is malformed.

If you can't fix the database when its in this state, maybe you can try to download it again if and when this error occurs (assuming that this problem is rare and downloading the database again can fix the problem).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文