google-ar / sceneform-android-sdk

Sceneform SDK for Android
https://developers.google.com/sceneform/develop/
Apache License 2.0
1.23k stars 604 forks source link

[Question]Loading .sfb file from Internal Storage #528

Closed yashvv closed 5 years ago

yashvv commented 5 years ago

Hi, Is there support to load .sfb files from Device Storage. There is support for externally stored assets and downloading at run time. Is there any plan to support this feature?

Currently the issue is that we need to request a lot of permissions from the user (Camera access, Install AR Core, Write to External Storage). The user experience will not be good and to download the whole experience at runtime will be a ton of overhead on the data and load times. If there is support to load from Internal storage it will make loading the assets faster and more secure.

We have an experience where the model cannot be revealed to others. If they are written to external storage then they will have to be encrypted and decrypted at run time which also adds some overhead and requesting an additional permission.

Can you please add this feature if this does not exist?

Any suggestions for better asset management. Feel free to comment

ishaang10 commented 5 years ago

i also have the same issue. ive managed to download model and have access to the content URI. now i also want to load the model using this content uri

fredsa commented 5 years ago

You can load the model file from private app storage and provide the contents as an InputStream.

You should also be able to use file: URI, or path starting with a / to access files from package private storage.

jonas-kgomo commented 5 years ago

@ishaang10 Have you solved this issue?

ishaang10 commented 5 years ago

yes i have solved this but not in a proper way... Some steps which i did are as follows-

  1. download file from aws storage using Download manager in android studio..
  2. then copy the file in the persistent path manualy and delete the previously downloaded file.
  3. then using inputfile stream open the file and load it . thisnworked for me.try it and tell me if you are able to do it. else ill share the code directly
jonas-kgomo commented 5 years ago

I would appreciate if you share the code.

  1. I am also using Download Manager to download andy.sfb raw from the repo.
  2. This is interesting, I will try it with a pre-existing file.
  3. I attempted many times to use this method as you posted in other issues
  File file = new File("/storage/emulated/0/Download/andy.sfb");
        Callable callable = new Callable() {
            @Override
            public InputStream call() throws Exception {
                InputStream inputStream = new FileInputStream(file);
                return inputStream;
            }
        };

        ModelRenderable.builder()
                .setSource(this, callable )
                .build()
                .thenAccept(renderable -> andyRenderable = renderable)
                .exceptionally(
                        throwable -> {
                            Toast toast =
                                    Toast.makeText(this, "Unable to load andy renderable", Toast.LENGTH_LONG);
                            toast.setGravity(Gravity.CENTER, 0, 0);
                            toast.show();
                            return null;
                        });
ishaang10 commented 5 years ago

Can you tell me wats your issue exactly?? like is the app crashing or model is not getting rendered(only a ring without the model displayed). also can you share you log maybe?

ishaang10 commented 5 years ago

and please before proceding can youe pls check if the file exists or not.. using the file.exists() method. Also your app should have access to the phone's memory so make sure you have added all the required permissions

jonas-kgomo commented 5 years ago

The model is not getting rendered. The app doesnt crash at all.

I have also presented the issue here

I have made the application show the path where it saved and also the download notifies me when its finished, and i can access it, here it shows the toast

I have this permissions :

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

jonas-kgomo commented 5 years ago

With testing file.exists() method, I get I/System.out: Exists I pushed the project to github Logs are here : logcat.pdf

ishaang10 commented 5 years ago

go to device settings->apps and features-> your_app_name and check if the permissions for storage are checked....

If not then check it and test your app again

[you need to provide additional runtime permissions]

jonas-kgomo commented 5 years ago

Okay. I just enabled that feature from the device. But still doesn't render.

My device is not rooted

ishaang10 commented 5 years ago
 File file = new File("/storage/emulated/0/Download/model.sfb");
Callable<InputStream> callable = () -> new FileInputStream(file);

 ModelRenderable.builder()
            .setSource(getApplicationContext(), callable)
            .build()
            .thenAccept(renderable -> modelren = renderable)
            .exceptionally(
                    throwable -> {
                        Toast toast =
                                Toast.makeText(getApplicationContext(), "Unable to load andy renderable", Toast.LENGTH_LONG);
                        toast.setGravity(Gravity.CENTER, 0, 0);
                        toast.show();
                        return null;
                    });

Try this.

Dont forget to enable storage permissions in settings

if still not resolved can you please share a snapshot of whats happening.

ishaang10 commented 5 years ago

i used this to add additional runtime storage permissions ..

 @Override`
    public String[] getAdditionalPermissions() {
        String[] additionalPermissions = super.getAdditionalPermissions();

        int permissionLength = additionalPermissions != null ? additionalPermissions.length : 0;

        String[] permissions = new String[permissionLength + 1];

        permissions[0] = Manifest.permission.WRITE_EXTERNAL_STORAGE;

        if (permissionLength > 0) {
            System.arraycopy(additionalPermissions,
                    0,
                    permissions,
                    1,
                    additionalPermissions.length);
        }
        return permissions;
       }
jonas-kgomo commented 5 years ago

This worked like magic. Thanks @ishaang10

ishaang10 commented 5 years ago

thanks sir. happy to help you :)

jingxuan98 commented 4 years ago

You can load the model file from private app storage and provide the contents as an InputStream.

You should also be able to use file: URI, or path starting with a / to access files from package private storage.

@fredsa I am having a problem which I can get the content Uri from the .gItf from local storage but how can I convert to file: URI or starting with /? Can you provide some examples?

https://github.com/google-ar/sceneform-android-sdk/issues/945

Here is my issue

iShelar commented 4 years ago

I tried this all solutions..but It cant render the .sfb file from local storage.

iShelar commented 4 years ago

@Override` public String[] getAdditionalPermissions() { String[] additionalPermissions = super.getAdditionalPermissions();

    int permissionLength = additionalPermissions != null ? additionalPermissions.length : 0;

    String[] permissions = new String[permissionLength + 1];

    permissions[0] = Manifest.permission.WRITE_EXTERNAL_STORAGE;

    if (permissionLength > 0) {
        System.arraycopy(additionalPermissions,
                0,
                permissions,
                1,
                additionalPermissions.length);
    }
    return permissions;
   }

Not worked for me