Merge "Support the rich content for accessibility service (1/n)"
This commit is contained in:
33
res/layout/preference_animated_image.xml
Normal file
33
res/layout/preference_animated_image.xml
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2019 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipToPadding="false"
|
||||
android:importantForAccessibility="noHideDescendants">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/animated_img"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:focusable="false"
|
||||
android:clickable="false"
|
||||
android:adjustViewBounds="true"/>
|
||||
</FrameLayout>
|
65
res/layout/preference_static_text.xml
Normal file
65
res/layout/preference_static_text.xml
Normal file
@@ -0,0 +1,65 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2019 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:clipToPadding="false">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/icon_frame"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:minWidth="56dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="4dp">
|
||||
<ImageView
|
||||
android:id="@+android:id/icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
</FrameLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="16dp"
|
||||
android:paddingTop="16dp">
|
||||
|
||||
<TextView android:id="@+android:id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<TextView android:id="@+android:id/summary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@android:id/title"
|
||||
android:layout_alignStart="@android:id/title"
|
||||
android:textColor="?android:attr/textColorSecondary"/>
|
||||
</RelativeLayout>
|
||||
|
||||
<LinearLayout android:id="@+android:id/widget_frame"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="vertical" />
|
||||
</LinearLayout>
|
@@ -164,7 +164,10 @@ public class AccessibilityDetailsSettingsFragment extends InstrumentedFragment {
|
||||
new ComponentName(packageName, settingsClassName).flattenToString());
|
||||
}
|
||||
extras.putParcelable(AccessibilitySettings.EXTRA_COMPONENT_NAME, componentName);
|
||||
extras.putInt(AccessibilitySettings.EXTRA_ANIMATED_IMAGE_RES, info.getAnimatedImageRes());
|
||||
|
||||
final String htmlDescription = info.loadHtmlDescription(getActivity().getPackageManager());
|
||||
extras.putString(AccessibilitySettings.EXTRA_HTML_DESCRIPTION, htmlDescription);
|
||||
return extras;
|
||||
}
|
||||
|
||||
|
@@ -111,6 +111,8 @@ public class AccessibilitySettings extends DashboardFragment {
|
||||
static final String EXTRA_SETTINGS_COMPONENT_NAME = "settings_component_name";
|
||||
static final String EXTRA_VIDEO_RAW_RESOURCE_ID = "video_resource";
|
||||
static final String EXTRA_LAUNCHED_FROM_SUW = "from_suw";
|
||||
static final String EXTRA_ANIMATED_IMAGE_RES = "animated_image_res";
|
||||
static final String EXTRA_HTML_DESCRIPTION = "html_description";
|
||||
|
||||
// Timeout before we update the services if packages are added/removed
|
||||
// since the AccessibilityManagerService has to do that processing first
|
||||
@@ -409,6 +411,10 @@ public class AccessibilitySettings extends DashboardFragment {
|
||||
extras.putString(EXTRA_TITLE, title);
|
||||
extras.putParcelable(EXTRA_RESOLVE_INFO, resolveInfo);
|
||||
extras.putString(EXTRA_SUMMARY, description);
|
||||
extras.putInt(EXTRA_ANIMATED_IMAGE_RES, info.getAnimatedImageRes());
|
||||
|
||||
final String htmlDescription = info.loadHtmlDescription(getPackageManager());
|
||||
extras.putString(AccessibilitySettings.EXTRA_HTML_DESCRIPTION, htmlDescription);
|
||||
|
||||
final String settingsClassName = info.getSettingsActivityName();
|
||||
if (!TextUtils.isEmpty(settingsClassName)) {
|
||||
|
@@ -169,6 +169,9 @@ public class AccessibilitySettingsForSetupWizard extends SettingsPreferenceFragm
|
||||
description = getString(R.string.accessibility_service_default_description);
|
||||
}
|
||||
extras.putString(AccessibilitySettings.EXTRA_SUMMARY, description);
|
||||
|
||||
final String htmlDescription = info.loadHtmlDescription(getPackageManager());
|
||||
extras.putString(AccessibilitySettings.EXTRA_HTML_DESCRIPTION, htmlDescription);
|
||||
}
|
||||
|
||||
private static void configureMagnificationPreferenceIfNeeded(Preference preference) {
|
||||
|
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.accessibility;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.AnimatedImageDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
/**
|
||||
* A custom {@link ImageView} preference for showing animated or static image, such as <a
|
||||
* href="https://developers.google.com/speed/webp/">animated webp</a> and static png.
|
||||
*/
|
||||
public class AnimatedImagePreference extends Preference {
|
||||
|
||||
private boolean mDividerAllowedAbove = false;
|
||||
private Uri mImageUri;
|
||||
|
||||
AnimatedImagePreference(Context context) {
|
||||
super(context);
|
||||
setLayoutResource(R.layout.preference_animated_image);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(PreferenceViewHolder holder) {
|
||||
super.onBindViewHolder(holder);
|
||||
holder.setDividerAllowedAbove(mDividerAllowedAbove);
|
||||
|
||||
final ImageView imageView = holder.itemView.findViewById(R.id.animated_img);
|
||||
if (imageView != null && mImageUri != null) {
|
||||
imageView.setImageURI(mImageUri);
|
||||
|
||||
final Drawable drawable = imageView.getDrawable();
|
||||
if (drawable != null) {
|
||||
if (drawable instanceof AnimatedImageDrawable) {
|
||||
((AnimatedImageDrawable) drawable).start();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets divider whether to show in preference above.
|
||||
*
|
||||
* @param allowed true will be drawn on above this item
|
||||
*/
|
||||
public void setDividerAllowedAbove(boolean allowed) {
|
||||
if (allowed != mDividerAllowedAbove) {
|
||||
mDividerAllowedAbove = allowed;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set image uri to display image in {@link ImageView}
|
||||
*
|
||||
* @param imageUri the Uri of an image
|
||||
*/
|
||||
public void setImageUri(Uri imageUri) {
|
||||
if (imageUri != null && !imageUri.equals(mImageUri)) {
|
||||
mImageUri = imageUri;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
}
|
139
src/com/android/settings/accessibility/HtmlTextPreference.java
Normal file
139
src/com/android/settings/accessibility/HtmlTextPreference.java
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.accessibility;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.Html;
|
||||
import android.text.TextUtils;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* A custom {@link android.widget.TextView} preference that shows html text with a custom tag
|
||||
* filter.
|
||||
*/
|
||||
public final class HtmlTextPreference extends StaticTextPreference {
|
||||
|
||||
private boolean mDividerAllowedAbove = false;
|
||||
private int mFlag = Html.FROM_HTML_MODE_COMPACT;
|
||||
private Html.ImageGetter mImageGetter;
|
||||
private Html.TagHandler mTagHandler;
|
||||
private List<String> mUnsupportedTagList;
|
||||
|
||||
HtmlTextPreference(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(PreferenceViewHolder holder) {
|
||||
super.onBindViewHolder(holder);
|
||||
holder.setDividerAllowedAbove(mDividerAllowedAbove);
|
||||
|
||||
final TextView summaryView = holder.itemView.findViewById(android.R.id.summary);
|
||||
if (summaryView != null && !TextUtils.isEmpty(getSummary())) {
|
||||
final String filteredText = getFilteredText(getSummary().toString());
|
||||
summaryView.setText(Html.fromHtml(filteredText, mFlag, mImageGetter, mTagHandler));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets divider whether to show in preference above.
|
||||
*
|
||||
* @param allowed true will be drawn on above this item
|
||||
*/
|
||||
public void setDividerAllowedAbove(boolean allowed) {
|
||||
if (allowed != mDividerAllowedAbove) {
|
||||
mDividerAllowedAbove = allowed;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the flag to which text format to be applied.
|
||||
*
|
||||
* @param flag to indicate that html text format
|
||||
*/
|
||||
public void setFlag(int flag) {
|
||||
if (flag != mFlag) {
|
||||
mFlag = flag;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets image getter and help to load corresponding images when parsing.
|
||||
*
|
||||
* @param imageGetter to load image by image tag content
|
||||
*/
|
||||
public void setImageGetter(Html.ImageGetter imageGetter) {
|
||||
if (imageGetter != null && !imageGetter.equals(mImageGetter)) {
|
||||
mImageGetter = imageGetter;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets tag handler to handle the unsupported tags.
|
||||
*
|
||||
* @param tagHandler the handler for unhandled tags
|
||||
*/
|
||||
public void setTagHandler(Html.TagHandler tagHandler) {
|
||||
if (tagHandler != null && !tagHandler.equals(mTagHandler)) {
|
||||
mTagHandler = tagHandler;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets unsupported tag list, the text will be filtered though this list in advanced.
|
||||
*
|
||||
* @param unsupportedTagList the list of unsupported tags
|
||||
*/
|
||||
public void setUnsupportedTagList(List<String> unsupportedTagList) {
|
||||
if (unsupportedTagList != null && !unsupportedTagList.equals(mUnsupportedTagList)) {
|
||||
mUnsupportedTagList = unsupportedTagList;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private String getFilteredText(String text) {
|
||||
if (mUnsupportedTagList == null) {
|
||||
return text;
|
||||
}
|
||||
|
||||
int i = 1;
|
||||
for (String tag : mUnsupportedTagList) {
|
||||
if (!TextUtils.isEmpty(text)) {
|
||||
final String index = String.valueOf(i++);
|
||||
final String targetStart1 = "(?i)<" + tag + " ";
|
||||
final String targetStart2 = "(?i)<" + tag + ">";
|
||||
final String replacementStart1 = "<unsupportedtag" + index + " ";
|
||||
final String replacementStart2 = "<unsupportedtag" + index + ">";
|
||||
final String targetEnd = "(?i)</" + tag + ">";
|
||||
final String replacementEnd = "</unsupportedtag" + index + ">";
|
||||
text = Pattern.compile(targetStart1).matcher(text).replaceAll(replacementStart1);
|
||||
text = Pattern.compile(targetStart2).matcher(text).replaceAll(replacementStart2);
|
||||
text = Pattern.compile(targetEnd).matcher(text).replaceAll(replacementEnd);
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
}
|
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.accessibility;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
/**
|
||||
* A custom {@link android.widget.TextView} preference that removes the title and summary
|
||||
* restriction from platform {@link Preference} implementation and the icon location is kept as
|
||||
* gravity top instead of center.
|
||||
*/
|
||||
public class StaticTextPreference extends Preference {
|
||||
|
||||
StaticTextPreference(Context context) {
|
||||
super(context);
|
||||
setLayoutResource(R.layout.preference_static_text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(PreferenceViewHolder holder) {
|
||||
super.onBindViewHolder(holder);
|
||||
}
|
||||
}
|
@@ -24,6 +24,7 @@ import android.app.Dialog;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.ComponentName;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
@@ -69,8 +70,6 @@ public class ToggleAccessibilityServicePreferenceFragment extends ToggleFeatureP
|
||||
}
|
||||
};
|
||||
|
||||
private ComponentName mComponentName;
|
||||
|
||||
private Dialog mDialog;
|
||||
|
||||
private final View.OnClickListener mViewOnClickListener =
|
||||
@@ -341,5 +340,15 @@ public class ToggleAccessibilityServicePreferenceFragment extends ToggleFeatureP
|
||||
}
|
||||
|
||||
mComponentName = arguments.getParcelable(AccessibilitySettings.EXTRA_COMPONENT_NAME);
|
||||
|
||||
// Settings animated image.
|
||||
int animatedImageRes = arguments.getInt(AccessibilitySettings.EXTRA_ANIMATED_IMAGE_RES);
|
||||
mImageUri = new Uri.Builder().scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
|
||||
.authority(mComponentName.getPackageName())
|
||||
.appendPath(String.valueOf(animatedImageRes))
|
||||
.build();
|
||||
|
||||
// Settings html description.
|
||||
mHtmlDescription = arguments.getCharSequence(AccessibilitySettings.EXTRA_HTML_DESCRIPTION);
|
||||
}
|
||||
}
|
||||
|
@@ -16,10 +16,16 @@
|
||||
|
||||
package com.android.settings.accessibility;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.text.Html;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
@@ -29,7 +35,9 @@ import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settings.widget.SwitchBar;
|
||||
import com.android.settings.widget.ToggleSwitch;
|
||||
import com.android.settingslib.widget.FooterPreference;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class ToggleFeaturePreferenceFragment extends SettingsPreferenceFragment {
|
||||
|
||||
@@ -40,6 +48,30 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference
|
||||
|
||||
protected CharSequence mSettingsTitle;
|
||||
protected Intent mSettingsIntent;
|
||||
protected ComponentName mComponentName;
|
||||
protected Uri mImageUri;
|
||||
protected CharSequence mStaticDescription;
|
||||
protected CharSequence mHtmlDescription;
|
||||
private static final String ANCHOR_TAG = "a";
|
||||
private static final String DRAWABLE_FOLDER = "drawable";
|
||||
|
||||
// For html description of accessibility service, third party developer must follow the rule,
|
||||
// such as <img src="R.drawable.fileName"/>, a11y settings will get third party resources
|
||||
// by this.
|
||||
private static final String IMG_PREFIX = "R.drawable.";
|
||||
|
||||
private ImageView mImageGetterCacheView;
|
||||
|
||||
private final Html.ImageGetter mImageGetter = (String str) -> {
|
||||
if (str != null && str.startsWith(IMG_PREFIX)) {
|
||||
final String fileName = str.substring(IMG_PREFIX.length());
|
||||
return getDrawableFromUri(Uri.parse(
|
||||
ContentResolver.SCHEME_ANDROID_RESOURCE + "://"
|
||||
+ mComponentName.getPackageName() + "/" + DRAWABLE_FOLDER + "/"
|
||||
+ fileName));
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
@@ -63,15 +95,45 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference
|
||||
onProcessArguments(getArguments());
|
||||
updateSwitchBarText(mSwitchBar);
|
||||
|
||||
PreferenceScreen preferenceScreen = getPreferenceScreen();
|
||||
|
||||
// Show the "Settings" menu as if it were a preference screen
|
||||
if (mSettingsTitle != null && mSettingsIntent != null) {
|
||||
PreferenceScreen preferenceScreen = getPreferenceScreen();
|
||||
Preference settingsPref = new Preference(preferenceScreen.getContext());
|
||||
settingsPref.setTitle(mSettingsTitle);
|
||||
settingsPref.setIconSpaceReserved(true);
|
||||
settingsPref.setIntent(mSettingsIntent);
|
||||
preferenceScreen.addPreference(settingsPref);
|
||||
}
|
||||
|
||||
if (mImageUri != null) {
|
||||
final AnimatedImagePreference animatedImagePreference = new AnimatedImagePreference(
|
||||
preferenceScreen.getContext());
|
||||
animatedImagePreference.setImageUri(mImageUri);
|
||||
animatedImagePreference.setDividerAllowedAbove(true);
|
||||
preferenceScreen.addPreference(animatedImagePreference);
|
||||
}
|
||||
|
||||
if (mStaticDescription != null) {
|
||||
final StaticTextPreference staticTextPreference = new StaticTextPreference(
|
||||
preferenceScreen.getContext());
|
||||
staticTextPreference.setSummary(mStaticDescription);
|
||||
preferenceScreen.addPreference(staticTextPreference);
|
||||
}
|
||||
|
||||
if (mHtmlDescription != null) {
|
||||
// For accessibility service, avoid malicious links made by third party developer
|
||||
final List<String> unsupportedTagList = new ArrayList<>();
|
||||
unsupportedTagList.add(ANCHOR_TAG);
|
||||
|
||||
final HtmlTextPreference htmlTextPreference = new HtmlTextPreference(
|
||||
preferenceScreen.getContext());
|
||||
htmlTextPreference.setSummary(mHtmlDescription);
|
||||
htmlTextPreference.setImageGetter(mImageGetter);
|
||||
htmlTextPreference.setUnsupportedTagList(unsupportedTagList);
|
||||
htmlTextPreference.setDividerAllowedAbove(true);
|
||||
preferenceScreen.addPreference(htmlTextPreference);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -139,17 +201,30 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference
|
||||
// Summary.
|
||||
if (arguments.containsKey(AccessibilitySettings.EXTRA_SUMMARY_RES)) {
|
||||
final int summary = arguments.getInt(AccessibilitySettings.EXTRA_SUMMARY_RES);
|
||||
createFooterPreference(getText(summary));
|
||||
mStaticDescription = getText(summary);
|
||||
} else if (arguments.containsKey(AccessibilitySettings.EXTRA_SUMMARY)) {
|
||||
final CharSequence summary = arguments.getCharSequence(
|
||||
AccessibilitySettings.EXTRA_SUMMARY);
|
||||
createFooterPreference(summary);
|
||||
mStaticDescription = summary;
|
||||
}
|
||||
}
|
||||
|
||||
private void createFooterPreference(CharSequence title) {
|
||||
final PreferenceScreen preferenceScreen = getPreferenceScreen();
|
||||
preferenceScreen.addPreference(new FooterPreference.Builder(getActivity()).setTitle(
|
||||
title).build());
|
||||
private Drawable getDrawableFromUri(Uri imageUri) {
|
||||
if (mImageGetterCacheView == null) {
|
||||
mImageGetterCacheView = new ImageView(getContext());
|
||||
}
|
||||
|
||||
mImageGetterCacheView.setAdjustViewBounds(true);
|
||||
mImageGetterCacheView.setImageURI(imageUri);
|
||||
|
||||
final Drawable drawable = mImageGetterCacheView.getDrawable().mutate();
|
||||
if (drawable != null) {
|
||||
drawable.setBounds(/* left= */0, /* top= */0, drawable.getIntrinsicWidth(),
|
||||
drawable.getIntrinsicHeight());
|
||||
}
|
||||
|
||||
mImageGetterCacheView.setImageURI(null);
|
||||
mImageGetterCacheView.setImageDrawable(null);
|
||||
return drawable;
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.accessibility;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.Editable;
|
||||
import android.text.Html;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.xml.sax.XMLReader;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/** Tests for {@link HtmlTextPreference} */
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public final class HtmlTextPreferenceTest {
|
||||
|
||||
private HtmlTextPreference mHtmlTextPreference;
|
||||
private PreferenceViewHolder mPreferenceViewHolder;
|
||||
private String mHandledTag;
|
||||
private final Html.TagHandler mTagHandler = new Html.TagHandler() {
|
||||
@Override
|
||||
public void handleTag(boolean opening, String tag, Editable editable, XMLReader xmlReader) {
|
||||
mHandledTag = tag;
|
||||
}
|
||||
};
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
final Context context = RuntimeEnvironment.application;
|
||||
mHtmlTextPreference = new HtmlTextPreference(context);
|
||||
|
||||
final LayoutInflater inflater = LayoutInflater.from(context);
|
||||
final View view =
|
||||
inflater.inflate(R.layout.preference_static_text, null);
|
||||
mPreferenceViewHolder = PreferenceViewHolder.createInstanceForTests(view);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnsupportedTagList_keepRealContentWithoutTag() {
|
||||
final List<String> testUnsupportedTagList = new ArrayList<>();
|
||||
testUnsupportedTagList.add("testTag");
|
||||
final String testStr = "<testTag>Real description</testTag>";
|
||||
final String expectedStr = "Real description";
|
||||
final String expectedTag = "unsupportedtag1";
|
||||
|
||||
mHtmlTextPreference.setUnsupportedTagList(testUnsupportedTagList);
|
||||
mHtmlTextPreference.setSummary(testStr);
|
||||
mHtmlTextPreference.setTagHandler(mTagHandler);
|
||||
mHtmlTextPreference.onBindViewHolder(mPreferenceViewHolder);
|
||||
|
||||
final TextView summaryView = mPreferenceViewHolder.itemView.findViewById(
|
||||
android.R.id.summary);
|
||||
assertThat(summaryView.getText().toString()).isEqualTo(expectedStr);
|
||||
assertThat(mHandledTag).isEqualTo(expectedTag);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user