Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Display files on Fragments not on BoxPreviewActivity #10

Open
minaEweida opened this issue Apr 26, 2017 · 13 comments
Open

Display files on Fragments not on BoxPreviewActivity #10

minaEweida opened this issue Apr 26, 2017 · 13 comments

Comments

@minaEweida
Copy link

Hi, I am trying to use box-android-preview-sdk, but I can't find any other way to display my files except using BoxPreviewActivity which pretty much handles everything yet my business case implies that I display the file inside an overlay which means I need to preview the selected file on a fragment not an activity.

What I am trying to do is to display the files using fragments on our application, but this is not possible through the SDK, or so I would think but I can't be sure because there is not enough documentation about this.

Is there any way that I can display the files on a fragment or not? I see that there is BoxPreviewFragment but I could not use it. Or is the only way to preview is using BoxPreviewActivity?

Another thing, we are displaying files that are stored on Box CMS, I already use BoxShareApi and pass the sharedLink to get the BoxItem so that I can use it with the preview SDK yet I always get the following error from the Preview SDK that the file is not found although I already got all its info using BoxShareApi

{"type":"error","status":404,"code":"not_found","context_info":{"errors":[{"reason":"invalid_parameter","name":"item","message":"Invalid value 'f_157150080898'. 'item' with value 'f_157150080898' not found"}]},"help_url":"http://developers.box.com/docs/#errors","message":"Not Found","request_id":"number removed for privacy458fe9dce896a7"}

We tried this approach with Box IOS Preview SDK and it works just fine, I just don't understand what am I missing from Android side? Is there a limitation in the android preview SDK that does not allow me to preview files on CMS unless I at least have collaborator access to it?

@doncung
Copy link
Contributor

doncung commented May 16, 2017

You can use the BoxPreviewViewPager and call the loadItem/s method on it.
You may also have to set various listeners on the view pager to handle different events from the view pager. For us the logic is in various activity impl methods depending on the different types of content being previewed, but if you know exactly what type of file you are previewing i.e. image or pdf you only need to handle that type.
The view pager has a generic listener you can set which will let you know when the fragment is loaded, unloaded, and visible. Then based on the type of fragment (you will need instanceof checks), the types of previewfragments which the view pager loads have various methods that can interact with them.

@minaEweida
Copy link
Author

@doncung thank you so much. I will give it a try.

@minaEweida
Copy link
Author

Hi @doncung, I tried the BoxPreviewViewPager as advised. Added it to my layout and made sure that the activity implements BoxPreviewExecutorProvider and implemented the api required for it as done in the BoxPreviewActivity

@Override
public BoxPreviewViewPager.BoxPreviewExecutor getPreviewExecutor() {
    if (PREVIEW_EXECUTOR == null) {
        PREVIEW_EXECUTOR = BoxPreviewViewPager.BoxPreviewExecutor.createInstance(getApplication());
    }
    return PREVIEW_EXECUTOR;
}

And then after my service call returns the boxFile I want to preview, I called loadItem and implemented PreviewController that is serializable

            Fragment previewFragment = getFragmentManager().findFragmentByTag("Preview");
            BoxPreviewViewPager boxPreviewViewPager = (BoxPreviewViewPager) previewFragment.getView().findViewById(R.id.box_preview_view_pager);
            boxPreviewViewPager.loadItem(new LighthouseBoxPreviewController(boxSharedLinkSession), boxFile);

// Preview Controller
class LighthouseBoxPreviewController implements Serializable, PreviewController {

    private BoxSession session;

    public LighthouseBoxPreviewController(BoxSession session) {
        this.session = session;
    }

    @Override
    public BoxSession getSession() {
        return session;
    }

    @Override
    public PreviewStorage getStorage() {
        return new PreviewStorage(session);
    }

    @Override
    public BoxApiPreview getApiPreview() {
        return new BoxApiPreview(session);
    }

    @Override
    public BoxApiFolder getApiFolder() {
        return new BoxApiFolder(session);
    }

    @Override
    public InputStream downloadThumbnail(BoxFile boxFile, int minSize) throws BoxException {
        return null;
    }
}

However, it still throws the exception I used to get when I tried to load it using BoxPreviewFragment

Process: com.ibm.cio.be.ppm, PID: 27130
android.view.InflateException: Binary XML file line #27: Binary XML file line #27: Error inflating class TextView
at android.view.LayoutInflater.inflate(LayoutInflater.java:539)
at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
at com.box.androidsdk.preview.fragments.BoxPreviewDefaultFragment.onCreateView(BoxPreviewDefaultFragment.java:51)
at com.box.androidsdk.preview.fragments.BoxPreviewMediaFragment.onCreateView(BoxPreviewMediaFragment.java:54)
at com.box.androidsdk.preview.fragments.BoxPreviewVideoFragment.onCreateView(BoxPreviewVideoFragment.java:92)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2189)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1299)
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1528)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1595)
at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:757)
at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2355)
at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2146)
at android.support.v4.app.FragmentManagerImpl.optimizeAndExecuteOps(FragmentManager.java:2098)
at android.support.v4.app.FragmentManagerImpl.execSingleAction(FragmentManager.java:1979)
at android.support.v4.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:626)
at android.support.v4.app.FragmentStatePagerAdapter.finishUpdate(FragmentStatePagerAdapter.java:166)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1268)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1116)
at android.support.v4.view.ViewPager.setAdapter(ViewPager.java:540)
at com.box.androidsdk.preview.BoxPreviewViewPager$4.run(BoxPreviewViewPager.java:207)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

Is there something that I am doing wrong? or Am I missing something?

@doncung
Copy link
Contributor

doncung commented May 24, 2017

Alright I'm able to repro in my sample app. Will dig into why this is happening.

@doncung
Copy link
Contributor

doncung commented May 25, 2017

So after some investigation this seems to be due to the way the layout is implemented. We'll evaluate a fix for this, but for now what you need to do is add a style to your activity that has at least the following:

<style name="previewsdk_dark_theme" parent="Theme.AppCompat.NoActionBar">
    <item name="boxPrimaryText">@color/box_previewsdk_primary_text_dark</item>
    <item name="boxSecondaryText">@color/box_previewsdk_secondary_text_dark</item>
</style

You should be able to use your own colors if you want, but I tried the following and do not get the crash.

@omkarhande-zz
Copy link

omkarhande-zz commented May 14, 2019

New version of the SDK requires implementation of

override fun getBrowseController(): BrowseController { }
What is expected here?

@lub0s
Copy link
Contributor

lub0s commented May 22, 2019

Try returning DefaultPreviewController(session)

@omkarhande-zz
Copy link

omkarhande-zz commented May 22, 2019

@lupajz there are two more
override fun getNotificationContentIntent(p0: Context?, p1: BoxSession?, p2: BoxFile?, p3:BoxFolder?): Intent {}

override fun execute(p0: Runnable?) {}

What about these?

@lub0s
Copy link
Contributor

lub0s commented May 22, 2019

What are you actually trying to build @omkarhande ? Are you trying to create a sample where you don't have to run an Activity to preview the BoxFile ?

If that's the case I put up a fork that seems to work with documents (haven't tested rest) https://github.com/lupajz/box-android-preview-sdk/tree/no_activity

If you could provide more details I could try to help.

But to clarify those 2 methods:

  1. getNotificationContentIntent - Should return an intent to start BoxPreviewActivity
  2. execute - should somehow execute the Runnable from parameter

@omkarhande-zz
Copy link

@lupajz I am trying to open files in fragment using the BoxPreviewViewPager

@lub0s
Copy link
Contributor

lub0s commented May 23, 2019

@omkarhande so the sample I've linked above should work for your case. You can see the changes here

@omkarhande-zz
Copy link

@lupajz this is what I did, based on your sample code. Getting a blank screen with this.

class FilePreviewFragment : androidx.fragment.app.Fragment() {
    lateinit var session:BoxSession
    private lateinit var boxId: String

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mixpanel = MixpanelAPI.getInstance(context, BuildConfig.MIXPANEL_TOKEN)
        BoxConfig.CLIENT_ID = BuildConfig.BOX_CLIENT_ID
        BoxConfig.CLIENT_SECRET = BuildConfig.BOX_CLIENT_SECRET

        boxId = FilePreviewFragmentArgs.fromBundle(arguments!!).boxFileId

        session = BoxSession(context!!, BuildConfig.BOX_ACCESSTOKEN, null)
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val view = inflater.inflate(R.layout.file_fragment_layout, container, false)
        box_preview_area?.init()
        session.authenticate(context) { response ->
            Logger.d("boxResponse = %s", response.isSuccess)
            val fileApi = BoxApiFile(session)
            var file: BoxFile? = null
            try {
                file = fileApi.getInfoRequest(boxId).send()
                Logger.d("boxfile = %s", file)
                val defaultPreviewController = DefaultPreviewController(session)
                box_preview_area?.fragmentListener = object : BoxPreviewFragment.Listener{
                    override fun onFragmentVisible(p0: BoxPreviewFragment?) {
                    }

                    override fun onFragmentLoaded(p0: BoxPreviewFragment?) {
                    }

                    override fun onFragmentTapped() {
                    }

                    override fun onError(p0: Exception?) {
                        p0?.message?.let { Logger.e(p0, it) }
                    }

                    override fun onFragmentUnloaded(p0: BoxPreviewFragment?) {
                    }

                    override fun onFragmentScrolled() {
                    }

                }

                box_preview_area.loadItem(defaultPreviewController, file)

            } catch (e: BoxException) {
                Logger.e("Boxfile error " + e.response, e)
            }
        }
        return view
    }
}

@lub0s
Copy link
Contributor

lub0s commented May 30, 2019

@omkarhande Can I also see the xml layout please ?
Do you get any logs from your code ?
Could you probably create a minimal project for me to clone and debug ?

From just looking at your code I believe that issue is that you are trying to access views using kotlin synthetic reference, namely box_preview_area in wrong lifecycle method.
box_preview_area in your case is in fact null because I think it is implemented as getView().findViewById(R.id. box_preview_area) by Kotlin compiler plugin. getView() in your case will result into null since the View will be available only after onViewCreated callback of the Fragment.

Anyway I've uploaded a video sample of what I'm getting from my example.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants