oasisfeng/condom

[doc] Some map SDK may access unwrapped context with View.getContext()

Closed this issue · 5 comments

Some map SDK requires developers put their MapView into layout file. For a example, amap use these demo code in their reference:

<com.amap.api.maps.MapView
    android:id="@+id/map"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

If we use these views in our layout xml, their views will be constructed in LayoutInflater of Activity and use Activity itself as Context. And then these SDK may access unwrapped context with View.getContext(). This also figures out why these map SDK just does not need a initialization method.

To prevent this, we can construct these views in Activity.onCreate() and add their to layout manually. For a example, following Kotlin code acts same as above layout written in xml:

map = MapView(CondomContext.wrap(this, "MapView")).apply {
    layoutParams = CoordinatorLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)
}
layout.addView(map, 0)

Replace this with applicationContext also work properly.

Do you have any better idea?

A similar issue and closed 1 years ago: #7
But it seems that they have not find this problem. So I open a new one. _(:з」∠)_

I'd suggest overridding onGetLayoutInflater() in Fragment:

@Override public LayoutInflater onGetLayoutInflater() {
    return super.onGetLayoutInflater().cloneInContext(CondomContext.wrap(getContext(), "MapView"));
}

This could save your code from complicated changes.

Work well in support library >= 25.4.0

However, Activity does not have a similar method and it has full control over layout inflate process of setContentView() actually. And frameworks' Fragment.onGetLayoutInflater() added in API level 26. Although these things are not recommended.

Since this issue aim to provide advice for project doc and usage, I will close it now.

@haruue For plain old activity and framework fragment, you can always grab a LayoutInflater and cloneInContext() then inflate() manually.

It's far simpler than creating the MapView manually.

Thanks for your use case, I've updated README with above instructions.