<NME> CapabilitiesPreference.java
<BEF> package cgeo.geocaching.settings;

import cgeo.geocaching.R;
import cgeo.geocaching.connector.ConnectorFactory;
import cgeo.geocaching.connector.IConnector;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.widget.TextView;

import androidx.preference.PreferenceViewHolder;

import org.apache.commons.lang3.StringUtils;

/**
 * Preference for displaying the supported capabilities of an {@link IConnector} implementation.
 */
public class CapabilitiesPreference extends AbstractAttributeBasedPreference {

    private String connectorCode;

    public CapabilitiesPreference(final Context context) {
        super(context);
    }

    public CapabilitiesPreference(final Context context, final AttributeSet attrs) {
        super(context, attrs);
    }

    public CapabilitiesPreference(final Context context, final AttributeSet attrs, final int defStyle) {
        super(context, attrs, defStyle);
    }

    private String createCapabilitiesMessage() {
        // TODO: this needs a better key for the connectors
        final IConnector connector = ConnectorFactory.getConnector(connectorCode + "1234");

        return StringUtils.join(connector.getCapabilities(), "\n");
    }

    @Override
    protected void processAttributeValues(final TypedArray values) {
        connectorCode = values.getString(0);
        setSummary(StringUtils.EMPTY);
    }

    @Override
    protected int[] getAttributeNames() {
        return new int[]{R.attr.connector};
    }

    @Override
    public void setSummary(final CharSequence summary) {
        super.setSummary(createCapabilitiesMessage());
    }

    @Override
    public void onBindViewHolder(final PreferenceViewHolder holder) {
        super.onBindViewHolder(holder);

        // there is a UI bug in the material preference implementation, see #12338
        final TextView summaryView = (TextView) holder.findViewById(android.R.id.summary);
        if (summaryView != null) {
            summaryView.setVerticalScrollBarEnabled(false);
        }
    }
        if (connector == null) {
            return StringUtils.EMPTY;
        }
        return connector.getCapabilitiesMessage();
    }

    @Override

<MSG> refactoring: generalize GCConnector capabilities implementation
<DFF> @@ -1,5 +1,6 @@
 package cgeo.geocaching.settings;
 
+import cgeo.geocaching.CgeoApplication;
 import cgeo.geocaching.R;
 import cgeo.geocaching.connector.ConnectorFactory;
 import cgeo.geocaching.connector.IConnector;
@@ -67,7 +68,15 @@ public class CapabilitiesPreference extends AbstractAttributeBasedPrefence {
         if (connector == null) {
             return StringUtils.EMPTY;
         }
-        return connector.getCapabilitiesMessage();
+        StringBuilder builder = new StringBuilder("<p>"
+                + CgeoApplication.getInstance().getString(R.string.feature_description) + "<ul>");
+
+        for (String capability : connector.getCapabilities()) {
+            builder.append("<li>").append(capability).append("</li>");
+        }
+
+        builder.append("</ul></p>");
+        return builder.toString();
     }
 
     @Override

refactoring: generalize GCConnector capabilities implementation