diff options
author | Philip P. Moltmann <moltmann@google.com> | 2018-08-27 14:40:25 -0700 |
---|---|---|
committer | Philip P. Moltmann <moltmann@google.com> | 2018-08-29 09:26:12 -0700 |
commit | 51c6c4c2b8328ae35327a93efba3818736fe5f72 (patch) | |
tree | e59bf5f5b588aa0f0ce46f077ee286c9db6fea34 /packages/SettingsLib/HelpUtils | |
parent | c8344a19637ff39f84cbd6acecb952c80f2c4de5 (diff) |
Factor out HelpUtils into @SystemAPI lib
This is the first of a few sub-libraries that will get factored out of
the settings lib. These libs will be included by mainline modules which
are compiles against system-api.
Bug: 110953302
Test: Looked at UI
m -j RunRoboSettingsLibTests
Change-Id: I16347e565aca554d6a8653df35765c2194479e78
Diffstat (limited to 'packages/SettingsLib/HelpUtils')
5 files changed, 328 insertions, 0 deletions
diff --git a/packages/SettingsLib/HelpUtils/Android.bp b/packages/SettingsLib/HelpUtils/Android.bp new file mode 100644 index 000000000000..af60185adc8b --- /dev/null +++ b/packages/SettingsLib/HelpUtils/Android.bp @@ -0,0 +1,9 @@ +android_library { + name: "SettingsLibHelpUtils", + + srcs: ["src/**/*.java"], + resource_dirs: ["res"], + + sdk_version: "system_current", + min_sdk_version: "21", +} diff --git a/packages/SettingsLib/HelpUtils/AndroidManifest.xml b/packages/SettingsLib/HelpUtils/AndroidManifest.xml new file mode 100644 index 000000000000..35b3933e379c --- /dev/null +++ b/packages/SettingsLib/HelpUtils/AndroidManifest.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2018 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. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.settingslib.helputils"> + + <uses-sdk android:minSdkVersion="21" /> + +</manifest> diff --git a/packages/SettingsLib/HelpUtils/res/drawable/ic_help_actionbar.xml b/packages/SettingsLib/HelpUtils/res/drawable/ic_help_actionbar.xml new file mode 100644 index 000000000000..9089a930c254 --- /dev/null +++ b/packages/SettingsLib/HelpUtils/res/drawable/ic_help_actionbar.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2017 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. + --> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + android:tint="?android:attr/colorControlNormal"> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M11,18h2v-2h-2V18zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10s10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8s8,3.59 8,8S16.41,20 12,20zM12,6c-2.21,0 -4,1.79 -4,4h2c0,-1.1 0.9,-2 2,-2s2,0.9 2,2c0,2 -3,1.75 -3,5h2c0,-2.25 3,-2.5 3,-5C16,7.79 14.21,6 12,6z"/> +</vector> diff --git a/packages/SettingsLib/HelpUtils/res/values/strings.xml b/packages/SettingsLib/HelpUtils/res/values/strings.xml new file mode 100644 index 000000000000..ae07f5de852b --- /dev/null +++ b/packages/SettingsLib/HelpUtils/res/values/strings.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2018 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. + --> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <!-- Label for Help and feedback menu item --> + <string name="help_feedback_label">Help & feedback</string> + +</resources>
\ No newline at end of file diff --git a/packages/SettingsLib/HelpUtils/src/com/android/settingslib/HelpUtils.java b/packages/SettingsLib/HelpUtils/src/com/android/settingslib/HelpUtils.java new file mode 100644 index 000000000000..7306d968a709 --- /dev/null +++ b/packages/SettingsLib/HelpUtils/src/com/android/settingslib/HelpUtils.java @@ -0,0 +1,246 @@ +/* + * Copyright (C) 2012 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.settingslib; + +import android.app.Activity; +import android.content.ActivityNotFoundException; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager.NameNotFoundException; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.net.Uri; +import android.provider.Settings.Global; +import android.text.TextUtils; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.MenuItem.OnMenuItemClickListener; + +import java.net.URISyntaxException; +import java.util.Locale; + +import com.android.settingslib.helputils.R; + +/** + * Functions to easily prepare contextual help menu option items with an intent that opens up the + * browser to a particular URL, while taking into account the preferred language and app version. + */ +public class HelpUtils { + private final static String TAG = HelpUtils.class.getSimpleName(); + + private static final int MENU_HELP = Menu.FIRST + 100; + + /** + * Help URL query parameter key for the preferred language. + */ + private final static String PARAM_LANGUAGE_CODE = "hl"; + + /** + * Help URL query parameter key for the app version. + */ + private final static String PARAM_VERSION = "version"; + + // Constants for help intents. + private static final String EXTRA_CONTEXT = "EXTRA_CONTEXT"; + private static final String EXTRA_THEME = "EXTRA_THEME"; + private static final String EXTRA_PRIMARY_COLOR = "EXTRA_PRIMARY_COLOR"; + private static final String EXTRA_BACKUP_URI = "EXTRA_BACKUP_URI"; + + /** + * Cached version code to prevent repeated calls to the package manager. + */ + private static String sCachedVersionCode = null; + + /** Static helper that is not instantiable*/ + private HelpUtils() { } + + public static boolean prepareHelpMenuItem(Activity activity, Menu menu, String helpUri, + String backupContext) { + MenuItem helpItem = menu.add(0, MENU_HELP, 0, R.string.help_feedback_label); + helpItem.setIcon(R.drawable.ic_help_actionbar); + return prepareHelpMenuItem(activity, helpItem, helpUri, backupContext); + } + + public static boolean prepareHelpMenuItem(Activity activity, Menu menu, int helpUriResource, + String backupContext) { + MenuItem helpItem = menu.add(0, MENU_HELP, 0, R.string.help_feedback_label); + helpItem.setIcon(R.drawable.ic_help_actionbar); + return prepareHelpMenuItem(activity, helpItem, activity.getString(helpUriResource), + backupContext); + } + + /** + * Prepares the help menu item by doing the following. + * - If the helpUrlString is empty or null, the help menu item is made invisible. + * - Otherwise, this makes the help menu item visible and sets the intent for the help menu + * item to view the URL. + * + * @return returns whether the help menu item has been made visible. + */ + public static boolean prepareHelpMenuItem(final Activity activity, MenuItem helpMenuItem, + String helpUriString, String backupContext) { + if (Global.getInt(activity.getContentResolver(), Global.DEVICE_PROVISIONED, 0) == 0) { + return false; + } + if (TextUtils.isEmpty(helpUriString)) { + // The help url string is empty or null, so set the help menu item to be invisible. + helpMenuItem.setVisible(false); + + // return that the help menu item is not visible (i.e. false) + return false; + } else { + final Intent intent = getHelpIntent(activity, helpUriString, backupContext); + + // Set the intent to the help menu item, show the help menu item in the overflow + // menu, and make it visible. + if (intent != null) { + helpMenuItem.setOnMenuItemClickListener(new OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem item) { + /** + * TODO: Enable metrics logger for @SystemApi (b/111552654) + * + MetricsLogger.action(activity, + MetricsEvent.ACTION_SETTING_HELP_AND_FEEDBACK, + intent.getStringExtra(EXTRA_CONTEXT)); + */ + try { + activity.startActivityForResult(intent, 0); + } catch (ActivityNotFoundException exc) { + Log.e(TAG, "No activity found for intent: " + intent); + } + return true; + } + }); + helpMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); + helpMenuItem.setVisible(true); + } else { + helpMenuItem.setVisible(false); + return false; + } + + // return that the help menu item is visible (i.e., true) + return true; + } + } + + public static Intent getHelpIntent(Context context, String helpUriString, + String backupContext) { + if (Global.getInt(context.getContentResolver(), Global.DEVICE_PROVISIONED, 0) == 0) { + return null; + } + // Try to handle as Intent Uri, otherwise just treat as Uri. + try { + Intent intent = Intent.parseUri(helpUriString, + Intent.URI_ANDROID_APP_SCHEME | Intent.URI_INTENT_SCHEME); + addIntentParameters(context, intent, backupContext, true /* sendPackageName */); + ComponentName component = intent.resolveActivity(context.getPackageManager()); + if (component != null) { + return intent; + } else if (intent.hasExtra(EXTRA_BACKUP_URI)) { + // This extra contains a backup URI for when the intent isn't available. + return getHelpIntent(context, intent.getStringExtra(EXTRA_BACKUP_URI), + backupContext); + } else { + return null; + } + } catch (URISyntaxException e) { + } + // The help url string exists, so first add in some extra query parameters. + final Uri fullUri = uriWithAddedParameters(context, Uri.parse(helpUriString)); + + // Then, create an intent that will be fired when the user + // selects this help menu item. + Intent intent = new Intent(Intent.ACTION_VIEW, fullUri); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); + return intent; + } + + public static void addIntentParameters(Context context, Intent intent, String backupContext, + boolean sendPackageName) { + if (!intent.hasExtra(EXTRA_CONTEXT)) { + // Insert some context if none exists. + intent.putExtra(EXTRA_CONTEXT, backupContext); + } + + Resources resources = context.getResources(); + boolean includePackageName = + resources.getBoolean(android.R.bool.config_sendPackageName); + + if (sendPackageName && includePackageName) { + String[] packageNameKey = + {resources.getString(android.R.string.config_help_package_name_key)}; + String[] packageNameValue = + {resources.getString(android.R.string.config_help_package_name_value)}; + String helpIntentExtraKey = + resources.getString(android.R.string.config_help_intent_extra_key); + String helpIntentNameKey = + resources.getString(android.R.string.config_help_intent_name_key); + String feedbackIntentExtraKey = + resources.getString(android.R.string.config_feedback_intent_extra_key); + String feedbackIntentNameKey = + resources.getString(android.R.string.config_feedback_intent_name_key); + intent.putExtra(helpIntentExtraKey, packageNameKey); + intent.putExtra(helpIntentNameKey, packageNameValue); + intent.putExtra(feedbackIntentExtraKey, packageNameKey); + intent.putExtra(feedbackIntentNameKey, packageNameValue); + } + intent.putExtra(EXTRA_THEME, 0 /* Light theme */); + TypedArray array = context.obtainStyledAttributes(new int[]{android.R.attr.colorPrimary}); + intent.putExtra(EXTRA_PRIMARY_COLOR, array.getColor(0, 0)); + array.recycle(); + } + + /** + * Adds two query parameters into the Uri, namely the language code and the version code + * of the app's package as gotten via the context. + * @return the uri with added query parameters + */ + private static Uri uriWithAddedParameters(Context context, Uri baseUri) { + Uri.Builder builder = baseUri.buildUpon(); + + // Add in the preferred language + builder.appendQueryParameter(PARAM_LANGUAGE_CODE, Locale.getDefault().toString()); + + // Add in the package version code + if (sCachedVersionCode == null) { + // There is no cached version code, so try to get it from the package manager. + try { + // cache the version code + PackageInfo info = context.getPackageManager().getPackageInfo( + context.getPackageName(), 0); + sCachedVersionCode = Long.toString(info.getLongVersionCode()); + + // append the version code to the uri + builder.appendQueryParameter(PARAM_VERSION, sCachedVersionCode); + } catch (NameNotFoundException e) { + // Cannot find the package name, so don't add in the version parameter + // This shouldn't happen. + Log.wtf(TAG, "Invalid package name for context", e); + } + } else { + builder.appendQueryParameter(PARAM_VERSION, sCachedVersionCode); + } + + // Build the full uri and return it + return builder.build(); + } +} |