moust / phonegap-xapkreader

Cordova plugin to access files in APK Expansion Files
13 stars 17 forks source link

How do we get non-image files? #10

Closed agamemnus closed 9 years ago

agamemnus commented 10 years ago

Is it possible with this plugin? Trying to read audio, .json, and .css files just seems to crash everything.

Edit: Here's a log.

E/AndroidProtocolHandler( 4344): Unable to open content URL: content://org.apache.cordova.xapkreader.expansion/sets/safari/safari.json
W/System.err( 4344): java.lang.NullPointerException
W/System.err( 4344):    at com.android.vending.expansion.zipfile.APEZProvider.openAssetFile(APEZProvider.java:182)
W/System.err( 4344):    at android.content.ContentProvider.openTypedAssetFile(ContentProvider.java:1393)
W/System.err( 4344):    at android.content.ContentProvider.openTypedAssetFile(ContentProvider.java:1459)
W/System.err( 4344):    at android.content.ContentProvider$Transport.openTypedAssetFile(ContentProvider.java:342)
W/System.err( 4344):    at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1067)
I/chromium( 4344): [INFO:library_loader_hooks.cc(112)] Chromium logging enabled: level = 0, default verbosity = 0
W/System.err( 4344):    at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:907)
W/System.err( 4344):    at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:834)
W/System.err( 4344):    at org.apache.cordova.CordovaResourceApi.openForRead(CordovaResourceApi.java:269)
W/System.err( 4344):    at org.apache.cordova.IceCreamCordovaWebViewClient.shouldInterceptLoadRequest(IceCreamCordovaWebViewClient.java:64)
W/System.err( 4344):    at org.xwalk.core.XWalkResourceClient.shouldInterceptLoadRequest(XWalkResourceClient.java:199)
W/System.err( 4344):    at org.xwalk.core.internal.XWalkContentsClientBridge.shouldInterceptRequest(XWalkContentsClientBridge.java:204)
W/System.err( 4344):    at org.xwalk.core.internal.XWalkContent$XWalkIoThreadClientImpl.shouldInterceptRequest(XWalkContent.java:505)
W/System.err( 4344):    at dalvik.system.NativeStart.run(Native Method)
I/BrowserProcessMain( 4344): Initializing chromium process, renderers=0
F/chromium( 4344): [FATAL:jni_android.cc(216)] Check failed: false.
F/libc    ( 4344): Fatal signal 6 (SIGABRT) at 0x000010f8 (code=-6), thread 4395 (Chrome_IOThread)

Edit: Possibly fixed THAT one (will mention how later if this pans out), but here's another one:

E/FileSource( 2009): Failed to open file '/storage/emulated/0/content://org.apac
he.cordova.xapkreader.expansion/sets/safari/audio/rdn056.mp3'. (No such file or
directory)

Note that I am using the Media plugin on this.

agamemnus commented 10 years ago

Possibly fixed the second issue.

File.exists (via File plugin) doesn't work for APK expansion files. The code then tries setting the file to file = Environment.getExternalStorageDirectory().getPath() + "/" + file, creating a malformed URL. So, had to modify loadAudioFile in AudioPlayer.java:

    /**
     * load audio file
     * @throws IOException
     * @throws IllegalStateException
     * @throws SecurityException
     * @throws IllegalArgumentException
     */
    private void loadAudioFile(String file) throws IllegalArgumentException, SecurityException, IllegalStateException, IOException {
        if (this.isStreaming(file)) {
            this.player.setDataSource(file);
            this.player.setAudioStreamType(AudioManager.STREAM_MUSIC);
            //if it's a streaming file, play mode is implied
            this.setMode(MODE.PLAY);
            this.setState(STATE.MEDIA_STARTING);
            this.player.setOnPreparedListener(this);
            this.player.prepareAsync();

        } else {
            if (file.startsWith("/android_asset/")) {
                String f = file.substring(15);
                android.content.res.AssetFileDescriptor fd = this.handler.cordova.getActivity().getAssets().openFd(f);
                this.player.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
            } else {
                File fp = new File(file);
                if (fp.exists()) {
                    FileInputStream fileInputStream = new FileInputStream(file);
                    this.player.setDataSource(fileInputStream.getFD());
                    fileInputStream.close();
                } else {
                    String original_file = file;
                    file = Environment.getExternalStorageDirectory().getPath() + "/" + file;
                    File fp = new File(file);
                    if (fp.exists()) {
                        this.player.setDataSource(file);
                    } else {
                        FileInputStream fileInputStream = new FileInputStream(original_file);
                        this.player.setDataSource(fileInputStream.getFD());
                        fileInputStream.close();
                    }
                }
            }
            this.setState(STATE.MEDIA_STARTING);
            this.player.setOnPreparedListener(this);
            this.player.prepare();
            // Get duration
            this.duration = getDurationInSeconds();
        }
    }
}
moust commented 10 years ago

Have you try with an html audio tag to play your audio file or is it a necessity to use le Media plugin?

If the File plugin always concatenates files paths with external storage directory's base path it's a big problem for its compatibility with this plugin... :s

agamemnus commented 10 years ago

I have to use the Media plugin.

The audio tag doesn't run audio without click events (very bad for games..), can't play concurrent audio, and can't play short pieces of audio without a .5-1s delay. It's unusable for games.

The File plugin does not always concatenate -- it does this only when (new File.exists(file)) is false, so a better solution is to figure out why File.exists is returning false in this case. I don't know enough Java to do this.

agamemnus commented 10 years ago

I added a pull request although I barely know what I'm doing...:

https://github.com/apache/cordova-plugin-media/pull/27

agamemnus commented 10 years ago

Ok. It seems like the file really just isn't visible. The audio elements aren't being played.

agamemnus commented 10 years ago

Possibly this will help to fix it? (I don't know..)

https://github.com/mcfarljw/cordova-plugin-expansion/blob/master/src/android/ExpansionPlugin.java

agamemnus commented 10 years ago

Okay.

I did a day-long workaround around the Media issue: I am now using a modified version of @goldfire's howler.js (with preload buffers for long files) and loading my files via XMLHttpRequest and AudioContext: https://github.com/agamemnus/howler.js