Files cannot be read in Documents directory by Android Cinder?


#1

I am loading files from the firebase cloud using java’s Activity, there I confirm that files exist in the Documents directory.

    private void downloadCloudFiles(final String downloadRoot){
        FirebaseDatabase database = FirebaseDatabase.getInstance();
        DatabaseReference myRef = database.getReference(downloadRoot);
        myRef.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                // This method is called once with the initial value and again
                // whenever data at this location is updated.
                List<String> list = (List<String>)dataSnapshot.getValue();
                for (final String file: list) {
                    File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS);
                    if (!dir.exists()) {
                        dir.mkdir();
                    }
                    File localFile = new File(dir, file);
                    if (localFile.exists()){
                        System.out.println(localFile.getAbsolutePath() + " exists, skipping");
                    } else {
                        StorageReference fileRef = storageRef.child(downloadRoot).child(file);
                        fileRef.getFile(localFile).addOnSuccessListener(new OnSuccessListener<FileDownloadTask.TaskSnapshot>() {
                            @Override
                            public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot) {
                                System.out.println("Downloaded file " + file + " " + taskSnapshot.getBytesTransferred() + " bytes");
                            }
                        }).addOnFailureListener(new OnFailureListener() {
                            @Override
                            public void onFailure(@NonNull Exception exception) {
                                System.out.println("Failed to load file " + file);
                            }
                        });
                    }
                }
                Log.d(TAG, "Value is: " + value);
            }

            @Override
            public void onCancelled(DatabaseError error) {
                // Failed to read value
                Log.w(TAG, "Failed to read value.", error.toException());
            }
        });
    }

However, when I read them in the native cinder code:

try {
        console()<<"movie "<<moviePath.string() << endl;
        mMovie = cinder::android::video::MovieGl::create( moviePath );
        mMovie->setLoop(true);
        mMovie->play();
    }
    catch( ci::Exception &exc ) {
        console() << "Exception caught trying to load the movie from path: " << moviePath << ", what: " << exc.what() << std::endl;
        mMovie.reset();
    }

I am running into exception

I/cinder: movie /storage/emulated/0/Documents/heart.mov
I/libcinder...VideoPlayer: VideoPlayer.createFromFilePath
I/libcinder...VideoPlayer: VideoPlayer(String filePath): filePath=/storage/emulated/0/Documents/heart.mov
E/libcinder...VideoPlayer: VideoPlayer.initialize(String filePath) error: /storage/emulated/0/Documents/heart.mov
E/MediaPlayer-JNI: getVideoWidth failed
E/MediaPlayer-JNI: getVideoHeight failed
W/Adreno-ES20: <core_glTexImage2D:493>: GL_INVALID_ENUM
I/cinder_app: mCurrentTexture id: 4
I/libcinder...VideoPlayer: initializeTexture: texName=4
E/MediaPlayer-JNI: getVideoWidth failed
E/MediaPlayer-JNI: getVideoHeight failed
I/cinder_app: Video Size: 0x0
E/MediaPlayer: start called in state 1
E/MediaPlayer: error (-38, 0)
E/MediaPlayer: Error (-38,0)

I can see that the read operation is using the same path as the write.
Reading from assets folder works fine.

What am I missing? Maybe permissions?

Thanks

–8


#2
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

Do they help?
Bala.


#3

Thanks @balachandran_c – I already have those.

Looking at the VideoPlayer.java

private void initialize(String filePath) {
        initializeCommon();
        try {
            AssetManager am = CinderNativeActivity.getInstance().getAssets();
            AssetFileDescriptor afd = am.openFd(filePath);
            mMediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
            mMediaPlayer.prepare();
        }
        catch(Exception e) {
            Log.e(TAG, "VideoPlayer.initialize(String filePath) error: " + e.getMessage());
        }
        if( null != mMediaPlayer ) {
            mMediaPlayer.setOnCompletionListener(this);
        }
    }

It looks like it assumes that the files are in the assets directory of the app. AssetManager is managing the app’s resources.

–8


#4

I fixed this by modifying VideoPlayer.java as a hack:

    private void initialize(String filePath) {
        boolean isDoc = filePath.contains("Documents");
        initializeCommon();

        try {
            if (isDoc) {
                mMediaPlayer.setDataSource(context, Uri.parse(filePath));
            } else {
                AssetManager am = CinderNativeActivity.getInstance().getAssets();
                AssetFileDescriptor afd = am.openFd(filePath);
                mMediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
            }
            mMediaPlayer.prepare();
        }
        catch (IOException e) {
            Log.e(TAG, "IOException " + e.getMessage());
        }
        catch(Exception e) {
            Log.e(TAG, "VideoPlayer.initialize(String filePath) error: " + e.getMessage());
        }

        if( null != mMediaPlayer ) {
            mMediaPlayer.setOnCompletionListener(this);
        }
    }

and setting read permissions on downloaded cloud files:

localFile.setReadable(true, false);

–8