Shared.java revision 741ac6fffb3ee2441569412a28a1c4f3c2160d87
1fefcd700d6b4cf1c4402af74c50fb0e762472901Steve McKay/* 2fefcd700d6b4cf1c4402af74c50fb0e762472901Steve McKay * Copyright (C) 2015 The Android Open Source Project 3fefcd700d6b4cf1c4402af74c50fb0e762472901Steve McKay * 4fefcd700d6b4cf1c4402af74c50fb0e762472901Steve McKay * Licensed under the Apache License, Version 2.0 (the "License"); 5fefcd700d6b4cf1c4402af74c50fb0e762472901Steve McKay * you may not use this file except in compliance with the License. 6fefcd700d6b4cf1c4402af74c50fb0e762472901Steve McKay * You may obtain a copy of the License at 7fefcd700d6b4cf1c4402af74c50fb0e762472901Steve McKay * 8fefcd700d6b4cf1c4402af74c50fb0e762472901Steve McKay * http://www.apache.org/licenses/LICENSE-2.0 9fefcd700d6b4cf1c4402af74c50fb0e762472901Steve McKay * 10fefcd700d6b4cf1c4402af74c50fb0e762472901Steve McKay * Unless required by applicable law or agreed to in writing, software 11fefcd700d6b4cf1c4402af74c50fb0e762472901Steve McKay * distributed under the License is distributed on an "AS IS" BASIS, 12fefcd700d6b4cf1c4402af74c50fb0e762472901Steve McKay * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13fefcd700d6b4cf1c4402af74c50fb0e762472901Steve McKay * See the License for the specific language governing permissions and 14fefcd700d6b4cf1c4402af74c50fb0e762472901Steve McKay * limitations under the License. 15fefcd700d6b4cf1c4402af74c50fb0e762472901Steve McKay */ 16fefcd700d6b4cf1c4402af74c50fb0e762472901Steve McKay 17fefcd700d6b4cf1c4402af74c50fb0e762472901Steve McKaypackage com.android.documentsui; 18fefcd700d6b4cf1c4402af74c50fb0e762472901Steve McKay 19919231857d2add3afe51f06aaf41663a252c3e0eBen Kwaimport android.content.Context; 20741ac6fffb3ee2441569412a28a1c4f3c2160d87Aga Wronskaimport android.content.res.Configuration; 2155c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKayimport android.text.TextUtils; 228e3fd7676023738c04d099f2940a635ff0699717Ben Kwaimport android.text.format.DateUtils; 238e3fd7676023738c04d099f2940a635ff0699717Ben Kwaimport android.text.format.Time; 24741ac6fffb3ee2441569412a28a1c4f3c2160d87Aga Wronskaimport android.view.WindowManager; 25741ac6fffb3ee2441569412a28a1c4f3c2160d87Aga Wronskaimport android.app.AlertDialog; 26919231857d2add3afe51f06aaf41663a252c3e0eBen Kwa 2755c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKayimport java.text.Collator; 28c83baa0574ee9e34c0e06bda1ff08928d880ee36Steve McKayimport java.util.ArrayList; 29c83baa0574ee9e34c0e06bda1ff08928d880ee36Steve McKayimport java.util.List; 30c83baa0574ee9e34c0e06bda1ff08928d880ee36Steve McKay 314d0255f79cc92a5675d14b20f9cdf06ecb8d7109Steve McKay/** @hide */ 32fefcd700d6b4cf1c4402af74c50fb0e762472901Steve McKaypublic final class Shared { 3355c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay 340af8afd3309538dec784ed0c9c35b252a8213123Steve McKay public static final String TAG = "Documents"; 350af8afd3309538dec784ed0c9c35b252a8213123Steve McKay 360af8afd3309538dec784ed0c9c35b252a8213123Steve McKay public static final boolean DEBUG = true; 370af8afd3309538dec784ed0c9c35b252a8213123Steve McKay 38ae96780a8909476dca709b88dbae5ec9a2f0632cBen Kwa /** Intent action name to pick a copy destination. */ 39ae96780a8909476dca709b88dbae5ec9a2f0632cBen Kwa public static final String ACTION_PICK_COPY_DESTINATION = 40ae96780a8909476dca709b88dbae5ec9a2f0632cBen Kwa "com.android.documentsui.PICK_COPY_DESTINATION"; 41ae96780a8909476dca709b88dbae5ec9a2f0632cBen Kwa 42ae96780a8909476dca709b88dbae5ec9a2f0632cBen Kwa /** 43ae96780a8909476dca709b88dbae5ec9a2f0632cBen Kwa * Extra boolean flag for {@link ACTION_PICK_COPY_DESTINATION}, which 44ae96780a8909476dca709b88dbae5ec9a2f0632cBen Kwa * specifies if the destination directory needs to create new directory or not. 45ae96780a8909476dca709b88dbae5ec9a2f0632cBen Kwa */ 46ae96780a8909476dca709b88dbae5ec9a2f0632cBen Kwa public static final String EXTRA_DIRECTORY_COPY = "com.android.documentsui.DIRECTORY_COPY"; 47af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska public static final String EXTRA_STACK = "com.android.documentsui.STACK"; 48af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska 49af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska /** 50af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska * Extra flag used to store query of type String in the bundle. 51af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska */ 52af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska public static final String EXTRA_QUERY = "query"; 53af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska 54af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska /** 55af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska * Extra flag used to store state of type State in the bundle. 56af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska */ 57af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska public static final String EXTRA_STATE = "state"; 58af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska 59af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska /** 60af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska * Extra flag used to store type of DirectoryFragment's type ResultType type in the bundle. 61af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska */ 62af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska public static final String EXTRA_TYPE = "type"; 63af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska 64af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska /** 65af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska * Extra flag used to store root of type RootInfo in the bundle. 66af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska */ 67af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska public static final String EXTRA_ROOT = "root"; 68af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska 69af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska /** 70af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska * Extra flag used to store document of DocumentInfo type in the bundle. 71af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska */ 72af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska public static final String EXTRA_DOC = "document"; 73af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska 74af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska /** 75af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska * Extra flag used to store DirectoryFragment's selection of Selection type in the bundle. 76af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska */ 77af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska public static final String EXTRA_SELECTION = "selection"; 78af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska 79af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska /** 80af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska * Extra flag used to store DirectoryFragment's search mode of boolean type in the bundle. 81af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska */ 82af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska public static final String EXTRA_SEARCH_MODE = "searchMode"; 83af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska 84af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska /** 85af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska * Extra flag used to store DirectoryFragment's ignore state of boolean type in the bundle. 86af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska */ 87af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska public static final String EXTRA_IGNORE_STATE = "ignoreState"; 88ae96780a8909476dca709b88dbae5ec9a2f0632cBen Kwa 8955c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay 9055c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay /** 9155c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay * String prefix used to indicate the document is a directory. 9255c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay */ 9355c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay public static final char DIR_PREFIX = '\001'; 9455c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay 9555c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay private static final Collator sCollator; 9655c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay 9755c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay static { 9855c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay sCollator = Collator.getInstance(); 9955c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay sCollator.setStrength(Collator.SECONDARY); 10055c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay } 10155c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay 102919231857d2add3afe51f06aaf41663a252c3e0eBen Kwa /** 103919231857d2add3afe51f06aaf41663a252c3e0eBen Kwa * Generates a formatted quantity string. 104919231857d2add3afe51f06aaf41663a252c3e0eBen Kwa */ 105919231857d2add3afe51f06aaf41663a252c3e0eBen Kwa public static final String getQuantityString(Context context, int resourceId, int quantity) { 106919231857d2add3afe51f06aaf41663a252c3e0eBen Kwa return context.getResources().getQuantityString(resourceId, quantity, quantity); 107919231857d2add3afe51f06aaf41663a252c3e0eBen Kwa } 1088e3fd7676023738c04d099f2940a635ff0699717Ben Kwa 1098e3fd7676023738c04d099f2940a635ff0699717Ben Kwa public static String formatTime(Context context, long when) { 1108e3fd7676023738c04d099f2940a635ff0699717Ben Kwa // TODO: DateUtils should make this easier 1118e3fd7676023738c04d099f2940a635ff0699717Ben Kwa Time then = new Time(); 1128e3fd7676023738c04d099f2940a635ff0699717Ben Kwa then.set(when); 1138e3fd7676023738c04d099f2940a635ff0699717Ben Kwa Time now = new Time(); 1148e3fd7676023738c04d099f2940a635ff0699717Ben Kwa now.setToNow(); 1158e3fd7676023738c04d099f2940a635ff0699717Ben Kwa 1168e3fd7676023738c04d099f2940a635ff0699717Ben Kwa int flags = DateUtils.FORMAT_NO_NOON | DateUtils.FORMAT_NO_MIDNIGHT 1178e3fd7676023738c04d099f2940a635ff0699717Ben Kwa | DateUtils.FORMAT_ABBREV_ALL; 1188e3fd7676023738c04d099f2940a635ff0699717Ben Kwa 1198e3fd7676023738c04d099f2940a635ff0699717Ben Kwa if (then.year != now.year) { 1208e3fd7676023738c04d099f2940a635ff0699717Ben Kwa flags |= DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_SHOW_DATE; 1218e3fd7676023738c04d099f2940a635ff0699717Ben Kwa } else if (then.yearDay != now.yearDay) { 1228e3fd7676023738c04d099f2940a635ff0699717Ben Kwa flags |= DateUtils.FORMAT_SHOW_DATE; 1238e3fd7676023738c04d099f2940a635ff0699717Ben Kwa } else { 1248e3fd7676023738c04d099f2940a635ff0699717Ben Kwa flags |= DateUtils.FORMAT_SHOW_TIME; 1258e3fd7676023738c04d099f2940a635ff0699717Ben Kwa } 1268e3fd7676023738c04d099f2940a635ff0699717Ben Kwa 1278e3fd7676023738c04d099f2940a635ff0699717Ben Kwa return DateUtils.formatDateTime(context, when, flags); 1288e3fd7676023738c04d099f2940a635ff0699717Ben Kwa } 1298e3fd7676023738c04d099f2940a635ff0699717Ben Kwa 130c83baa0574ee9e34c0e06bda1ff08928d880ee36Steve McKay /** 131c83baa0574ee9e34c0e06bda1ff08928d880ee36Steve McKay * A convenient way to transform any list into a (parcelable) ArrayList. 132c83baa0574ee9e34c0e06bda1ff08928d880ee36Steve McKay * Uses cast if possible, else creates a new list with entries from {@code list}. 133c83baa0574ee9e34c0e06bda1ff08928d880ee36Steve McKay */ 134c83baa0574ee9e34c0e06bda1ff08928d880ee36Steve McKay public static <T> ArrayList<T> asArrayList(List<T> list) { 135c83baa0574ee9e34c0e06bda1ff08928d880ee36Steve McKay return list instanceof ArrayList 136c83baa0574ee9e34c0e06bda1ff08928d880ee36Steve McKay ? (ArrayList<T>) list 137c83baa0574ee9e34c0e06bda1ff08928d880ee36Steve McKay : new ArrayList<T>(list); 138c83baa0574ee9e34c0e06bda1ff08928d880ee36Steve McKay } 13955c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay 14055c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay /** 14155c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay * Compare two strings against each other using system default collator in a 14255c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay * case-insensitive mode. Clusters strings prefixed with {@link DIR_PREFIX} 14355c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay * before other items. 14455c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay */ 14555c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay public static int compareToIgnoreCaseNullable(String lhs, String rhs) { 14655c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay final boolean leftEmpty = TextUtils.isEmpty(lhs); 14755c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay final boolean rightEmpty = TextUtils.isEmpty(rhs); 14855c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay 14955c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay if (leftEmpty && rightEmpty) return 0; 15055c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay if (leftEmpty) return -1; 15155c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay if (rightEmpty) return 1; 15255c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay 15355c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay final boolean leftDir = (lhs.charAt(0) == DIR_PREFIX); 15455c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay final boolean rightDir = (rhs.charAt(0) == DIR_PREFIX); 15555c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay 15655c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay if (leftDir && !rightDir) return -1; 15755c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay if (rightDir && !leftDir) return 1; 15855c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay 15955c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay return sCollator.compare(lhs, rhs); 16055c00e7356d9f76e7378cf7c701b9a41cb7be6daSteve McKay } 161741ac6fffb3ee2441569412a28a1c4f3c2160d87Aga Wronska 162741ac6fffb3ee2441569412a28a1c4f3c2160d87Aga Wronska public static boolean isHardwareKeyboardAvailable(Context context) { 163741ac6fffb3ee2441569412a28a1c4f3c2160d87Aga Wronska return context.getResources().getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS; 164741ac6fffb3ee2441569412a28a1c4f3c2160d87Aga Wronska } 165741ac6fffb3ee2441569412a28a1c4f3c2160d87Aga Wronska 166741ac6fffb3ee2441569412a28a1c4f3c2160d87Aga Wronska public static void ensureKeyboardPresent(Context context, AlertDialog dialog) { 167741ac6fffb3ee2441569412a28a1c4f3c2160d87Aga Wronska if (!isHardwareKeyboardAvailable(context)) { 168741ac6fffb3ee2441569412a28a1c4f3c2160d87Aga Wronska dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); 169741ac6fffb3ee2441569412a28a1c4f3c2160d87Aga Wronska } 170741ac6fffb3ee2441569412a28a1c4f3c2160d87Aga Wronska } 171741ac6fffb3ee2441569412a28a1c4f3c2160d87Aga Wronska 172fefcd700d6b4cf1c4402af74c50fb0e762472901Steve McKay} 173