165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane/* 265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Copyright (C) 2014 The Android Open Source Project 365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * 465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Licensed under the Apache License, Version 2.0 (the "License"); 565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * you may not use this file except in compliance with the License. 665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * You may obtain a copy of the License at 765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * 865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * http://www.apache.org/licenses/LICENSE-2.0 965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * 1065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Unless required by applicable law or agreed to in writing, software 1165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * distributed under the License is distributed on an "AS IS" BASIS, 1265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * See the License for the specific language governing permissions and 1465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * limitations under the License. 1565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 1665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 1765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lanepackage com.android.tv.settings.util; 1865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 1965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.ContentResolver; 2065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.Intent.ShortcutIconResource; 2165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.net.Uri; 2265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 2365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane/** 2465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Utilities for working with URIs. 2565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 2665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lanepublic final class UriUtils { 2765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 2865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final String SCHEME_SHORTCUT_ICON_RESOURCE = "shortcut.icon.resource"; 2965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final String SCHEME_DELIMITER = "://"; 3065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final String URI_PATH_DELIMITER = "/"; 3165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final String URI_PACKAGE_DELIMITER = ":"; 3265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final String HTTP_PREFIX = "http"; 3365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final String HTTPS_PREFIX = "https"; 3465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final String SCHEME_ACCOUNT_IMAGE = "image.account"; 3565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final String ACCOUNT_IMAGE_CHANGE_NOTIFY_URI = "change_notify_uri"; 3665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 3765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane /** 3865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Non instantiable. 3965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 4065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private UriUtils() {} 4165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 4265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane /** 4365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Gets a URI with short cut icon scheme. 4465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 4565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public static Uri getShortcutIconResourceUri(ShortcutIconResource iconResource) { 4665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return Uri.parse(SCHEME_SHORTCUT_ICON_RESOURCE + SCHEME_DELIMITER + iconResource.packageName 4765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane + URI_PATH_DELIMITER 4865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane + iconResource.resourceName.replace(URI_PACKAGE_DELIMITER, URI_PATH_DELIMITER)); 4965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 5065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 5165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane /** 5265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Checks if the URI refers to an Android resource. 5365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 5465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public static boolean isAndroidResourceUri(Uri uri) { 5565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return ContentResolver.SCHEME_ANDROID_RESOURCE.equals(uri.getScheme()); 5665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 5765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 5865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane /** 5965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Checks if the URI refers to an account image. 6065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 6165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public static boolean isAccountImageUri(Uri uri) { 626e995161147d9110d77ae1fe38b697e52891d3f2Tony Mantler return uri != null && SCHEME_ACCOUNT_IMAGE.equals(uri.getScheme()); 6365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 6465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 6565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public static String getAccountName(Uri uri) { 6665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (isAccountImageUri(uri)) { 676e995161147d9110d77ae1fe38b697e52891d3f2Tony Mantler return uri.getAuthority() + uri.getPath(); 6865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else { 6965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane throw new IllegalArgumentException("Invalid account image URI. " + uri); 7065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 7165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 7265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 7365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public static Uri getAccountImageChangeNotifyUri(Uri uri) { 7465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (isAccountImageUri(uri)) { 7565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane String notifyUri = uri.getQueryParameter(ACCOUNT_IMAGE_CHANGE_NOTIFY_URI); 7665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (notifyUri == null) { 7765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return null; 7865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else { 7965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return Uri.parse(notifyUri); 8065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 8165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else { 8265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane throw new IllegalArgumentException("Invalid account image URI. " + uri); 8365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 8465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 8565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 8665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane /** 8765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Returns {@code true} if the URI refers to a content URI which can be opened via 8865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * {@link ContentResolver#openInputStream(Uri)}. 8965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 9065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public static boolean isContentUri(Uri uri) { 9165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return ContentResolver.SCHEME_CONTENT.equals(uri.getScheme()) || 9265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ContentResolver.SCHEME_FILE.equals(uri.getScheme()); 9365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 9465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 9565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane /** 9665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Checks if the URI refers to an shortcut icon resource. 9765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 9865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public static boolean isShortcutIconResourceUri(Uri uri) { 9965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return SCHEME_SHORTCUT_ICON_RESOURCE.equals(uri.getScheme()); 10065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 10165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 10265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane /** 10365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Creates a shortcut icon resource object from an Android resource URI. 10465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 10565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public static ShortcutIconResource getIconResource(Uri uri) { 10665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if(isAndroidResourceUri(uri)) { 10765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ShortcutIconResource iconResource = new ShortcutIconResource(); 10865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane iconResource.packageName = uri.getAuthority(); 10965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // Trim off the scheme + 3 extra for "://", then replace the first "/" with a ":" 11065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane iconResource.resourceName = uri.toString().substring( 11165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ContentResolver.SCHEME_ANDROID_RESOURCE.length() + SCHEME_DELIMITER.length()) 11265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane .replaceFirst(URI_PATH_DELIMITER, URI_PACKAGE_DELIMITER); 11365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return iconResource; 11465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else if(isShortcutIconResourceUri(uri)) { 11565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ShortcutIconResource iconResource = new ShortcutIconResource(); 11665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane iconResource.packageName = uri.getAuthority(); 11765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane iconResource.resourceName = uri.toString().substring( 11865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane SCHEME_SHORTCUT_ICON_RESOURCE.length() + SCHEME_DELIMITER.length() 11965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane + iconResource.packageName.length() + URI_PATH_DELIMITER.length()) 12065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane .replaceFirst(URI_PATH_DELIMITER, URI_PACKAGE_DELIMITER); 12165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return iconResource; 12265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else { 12365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane throw new IllegalArgumentException("Invalid resource URI. " + uri); 12465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 12565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 12665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 12765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane /** 12865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Returns {@code true} if this is a web URI. 12965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 13065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public static boolean isWebUri(Uri resourceUri) { 13165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane String scheme = resourceUri.getScheme() == null ? null 13265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane : resourceUri.getScheme().toLowerCase(); 13365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return HTTP_PREFIX.equals(scheme) || HTTPS_PREFIX.equals(scheme); 13465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 13565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 13665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane} 137