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