GithubHelp home page GithubHelp logo

eggheadgames / android-file-asset-helper Goto Github PK

View Code? Open in Web Editor NEW
0.0 3.0 0.0 109 KB

Copy a versioned SQLite database from APK assets ready to use by SQLite in the app

License: MIT License

Java 100.00%

android-file-asset-helper's Introduction

Circle CI Release GitHub license

Android File Asset Helper

Copy a versioned file from APK assets ready to use in the regular read/write user file area of the Android device.

This library replaces android-sqlite-asset-helper and android-realm-asset-helper for use in the specialized scenario of copying a read-only database. However it could be used for any file that, say, can't be used within the bundle because only streaming access is provided.

E.g. an app might use a catalogue of data that is updated occaisionally. This data is opened read-only on the device and hence can be updated any time simply by copying over a new database.

Example

  • create an asset mydatabase_1.db in your Android assets
  • call this helper on app startup

If the numeric extension on the database has changed, then the mydatabase_1.db file will be copied and renamed to mydatabase.db. Any existing mydatabase.db will be replaced.

Later, when there is a new version of the catalogue data, the mydatabase_1.db file is replaced in the assets with mydatabase_2.db.

Installation Instructions

Add the JitPack.io repository to your root build.gradle:

allprojects {
    repositories {
        maven { url "https://jitpack.io" }
    }
}

Add a dependency to your application related build.gradle

dependencies {
    compile 'com.github.eggheadgames:android-file-asset-helper:x.x.x'
}

Alternatives

Originally I was using https://github.com/jgilfelt/android-sqlite-asset-helper but this is no longer maintained and I've had errors using the various forks with recent Android versions. So, for my very specific read-only scenario, I've adapted my similar https://github.com/eggheadgames/android-realm-asset-helper.

Android Room provides a mechanism for this. Here is a guide: https://medium.com/androiddevelopers/packing-the-room-pre-populate-your-database-with-this-one-method-333ae190e680

Explanation

It can be convenient to have a read-only database as part of an apk. This might have game level information, for example, or other data like zip codes or product information. If the app treats it as "read-only" (perhaps also using a separate realm database for storing other state data), then data updates are as simple as updating the "master" realm file in the apk and then copying it over on first run after the user updates.

iOS note: This is conceptually simpler in iOS, because database engines can access read-only data directly from the application bundle (= apk). This library was originally created so that our iOS and Android apps could share the same read-only SQLite database.

This helper library adds support for this "read-only data included in apk" scenario.

For efficiency, the copy should only be made when the database has changed. This is handled as follows:

  • if no copy of the database exists, it is copied
  • if a copy exists, then a sharedPreference value is checked to see what database version it is (defaults to 0 if not found)
  • the APK assets folder is searched for the database name with a postfix _NN in the name (e.g. products_12). If the NN value is higher than the current version, then the new database is copied (with the _NN removed) and the sharedPreference value is updated
  • if no database is found in assets, this causes an immediate error (as this is usually an oversight and should be resolved ASAP)

Thus, the workflow for an apk with read-only data becomes:

  • store the database, e.g. products in assets with the name products_0
  • when products is updated, rename the fie from products_0 to products_1

The helper will see the change and copy the database as needed.

Caveats

There is no consideration given (so far) to database migration requirements or any sort of "update my user's existing SQLite database from this new SQLite database". That is clearly a useful enhancement to think about for the future but was beyond the scope of the initial release.

Pull Requests, Issues, Feedback

We welcome pull requests. If you have questions or bugs, please open an issue and we'll respond promptly.

android-file-asset-helper's People

Contributors

alexdibrivnyy avatar eggheadgames avatar mikemee avatar

Watchers

 avatar  avatar  avatar

android-file-asset-helper's Issues

Problem copying file when subfolder doesn't exist

I had this problem on Android 5.1.1 (a Kindle) when doing a fresh install. My best guess is because the folder "databases" does not exist so it couldn't open the new file to copy it.

However, that's just a guess...

    java.lang.RuntimeException: Unable to create application com.egghead.LogicApp: java.lang.RuntimeException: java.io.FileNotFoundException: /data/data/com.eggheadgames.logicproblems/databases/data.db: open failed: ENOENT (No such file or directory)
        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4883)
        at android.app.ActivityThread.access$1500(ActivityThread.java:160)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1382)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5597)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:984)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)
     Caused by: java.lang.RuntimeException: java.io.FileNotFoundException: /data/data/com.eggheadgames.logicproblems/databases/data.db: open failed: ENOENT (No such file or directory)
        at com.eggheadgames.assethelper.OsUtil.loadFileToLocalStorage(OsUtil.java:42)
        at com.eggheadgames.assethelper.AssetHelper.loadFileToStorage(AssetHelper.java:119)
        at com.eggheadgames.assethelper.AssetHelper.copyIfNew(AssetHelper.java:42)
        at com.egghead.provider.ContentProvider.init(ContentProvider.java:45)
        at com.egghead.LogicApp.onCreate(LogicApp.java:47)
        at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1015)
        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4880)
        at android.app.ActivityThread.access$1500(ActivityThread.java:160) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1382) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:135) 
        at android.app.ActivityThread.main(ActivityThread.java:5597) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at java.lang.reflect.Method.invoke(Method.java:372) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:984) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779) 
     Caused by: java.io.FileNotFoundException: /data/data/com.eggheadgames.logicproblems/databases/data.db: open failed: ENOENT (No such file or directory)
        at libcore.io.IoBridge.open(IoBridge.java:456)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:89)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:74)
        at com.eggheadgames.assethelper.OsUtil.loadFileToLocalStorage(OsUtil.java:32)
        at com.eggheadgames.assethelper.AssetHelper.loadFileToStorage(AssetHelper.java:119) 
        at com.eggheadgames.assethelper.AssetHelper.copyIfNew(AssetHelper.java:42) 
        at com.egghead.provider.ContentProvider.init(ContentProvider.java:45) 
        at com.egghead.LogicApp.onCreate(LogicApp.java:47) 
        at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1015) 
        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4880) 
        at android.app.ActivityThread.access$1500(ActivityThread.java:160) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1382) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:135) 
        at android.app.ActivityThread.main(ActivityThread.java:5597) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at java.lang.reflect.Method.invoke(Method.java:372) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:984) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779) 
     Caused by: android.system.ErrnoException: open failed: ENOENT (No such file or directory)
        at libcore.io.Posix.open(Native Method)
        at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)
        at libcore.io.IoBridge.open(IoBridge.java:442)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:89) 
        at java.io.FileOutputStream.<init>(FileOutputStream.java:74) 
        at com.eggheadgames.assethelper.OsUtil.loadFileToLocalStorage(OsUtil.java:32) 
        at com.eggheadgames.assethelper.AssetHelper.loadFileToStorage(AssetHelper.java:119) 
        at com.eggheadgames.assethelper.AssetHelper.copyIfNew(AssetHelper.java:42) 
        at com.egghead.provider.ContentProvider.init(ContentProvider.java:45) 
        at com.egghead.LogicApp.onCreate(LogicApp.java:47) 
        at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1015) 
        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4880) 
        at android.app.ActivityThread.access$1500(ActivityThread.java:160) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1382) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:135) 
        at android.app.ActivityThread.main(ActivityThread.java:5597) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at java.lang.reflect.Method.invoke(Method.java:372) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:984) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779) 

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.