1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package androidx.wear.utils;
17 
18 import android.content.Context;
19 import android.content.pm.ApplicationInfo;
20 import android.content.pm.PackageManager;
21 
22 /**
23  * Constants for android wear apps which are related to manifest meta-data.
24  */
25 public class MetadataConstants {
26 
27     //  Constants for standalone apps. //
28 
29     /**
30      * The name of the meta-data element in the Wear app manifest for specifying whether this app
31      * does not require a companion phone app. The value should be set to "true" or "false".
32      * <p>
33      * <p>Wear apps that do not require a phone side companion app to function can declare this in
34      * their AndroidManifest.xml file by setting the standalone meta-data element to true as shown
35      * in the following example. If this value is true, all users can discover this app regardless
36      * of what phone they have. If this value is false (or not set), only users with compatible
37      * Android phones can discover this app.
38      * <p>
39      * <pre class="prettyprint">{@code
40      * <meta-data
41      * android:name="com.google.android.wearable.standalone"
42      * android:value="true" />
43      * }</pre>
44      */
45     public static final String STANDALONE_METADATA_NAME = "com.google.android.wearable.standalone";
46 
47     //  Constants for customizing bridging of notifications from the phone to the wearable. //
48 
49     /**
50      * We support specifying whether notifications should be bridged from the phone to the wearable
51      * in the Wear app manifest file. Simply add a meta-data element to the Wear app manifest with
52      * the name "com.google.android.wearable.notificationBridgeMode" and either the value
53      * NO_BRIDGING or the value BRIDGING. If you choose not to update your Wear app manifest, then
54      * notifications will be bridged by default from the phone to the wearable.
55      *
56      * <p>NO_BRIDGING means that phone notifications will not be bridged to the wearable if the
57      * wearable app is installed.
58      *
59      * <p>BRIDGING means that phone notifications will be bridged to the wearable, unless they are
60      * posted with
61      * {@link android.app.Notification.Builder#setLocalOnly(boolean) setLocalOnly(true)}.
62      *
63      * <p>Example AndroidManifest.xml meta-data element for NO_BRIDGING:
64      *
65      * <pre class="prettyprint">{@code
66      * <meta-data
67      *     android:name="com.google.android.wearable.notificationBridgeMode"
68      *     android:value="NO_BRIDGING" />
69      * }</pre>
70      *
71      * <p>Example AndroidManifest.xml meta-data element for BRIDGING:
72      *
73      * <pre class="prettyprint">{@code
74      * <meta-data
75      *     android:name="com.google.android.wearable.notificationBridgeMode"
76      *     android:value="BRIDGING" />
77      * }</pre>
78      */
79     public static final String NOTIFICATION_BRIDGE_MODE_METADATA_NAME =
80             "com.google.android.wearable.notificationBridgeMode";
81 
82     /**
83      * The value of the notification bridge mode meta-data element in the case where the Wear app
84      * wants notifications to be bridged from the phone to the wearable.
85      */
86     public static final String NOTIFICATION_BRIDGE_MODE_BRIDGING = "BRIDGING";
87 
88     /**
89      * The value of the notification bridge mode meta-data element in the case where the Wear app
90      * does not want notifications to be bridged from the phone to the wearable.
91      */
92     public static final String NOTIFICATION_BRIDGE_MODE_NO_BRIDGING = "NO_BRIDGING";
93 
94     //  Constants for watch face preview. //
95 
96     /**
97      * The name of the meta-data element in the watch face service manifest declaration used
98      * to assign a non-circular preview image to the watch face. The value should be set to
99      * a drawable reference.
100      *
101      * <pre class="prettyprint">
102      * &lt;meta-data
103      *     android:name="com.google.android.wearable.watchface.preview"
104      *     android:resource="@drawable/preview_face" /&gt;
105      * </pre>
106      */
107     public static final String WATCH_FACE_PREVIEW_METADATA_NAME =
108             "com.google.android.wearable.watchface.preview";
109 
110     /**
111      * The name of the meta-data element in the watch face service manifest declaration used
112      * to assign a circular preview image to the watch face. The value should be set to
113      * a drawable reference.
114      *
115      * <pre class="prettyprint">
116      * &lt;meta-data
117      *     android:name="com.google.android.wearable.watchface.preview_circular"
118      *     android:resource="@drawable/preview_face_circular" /&gt;
119      * </pre>
120      */
121     public static final String WATCH_FACE_PREVIEW_CIRCULAR_METADATA_NAME =
122             "com.google.android.wearable.watchface.preview_circular";
123 
124     // HELPER METHODS //
125 
126     /**
127      * Determines whether a given context comes from a standalone app. This can be used as a proxy
128      * to check if any given app is compatible with iOS Companion devices.
129      *
130      * @param context to be evaluated.
131      * @return Whether a given context comes from a standalone app.
132      */
133     @SuppressWarnings("deprecation")
isStandalone(Context context)134     public static boolean isStandalone(Context context) {
135         try {
136             ApplicationInfo appInfo = context.getPackageManager().getApplicationInfo(
137                     context.getPackageName(), PackageManager.GET_META_DATA);
138             if (appInfo.metaData != null) {
139                 return appInfo.metaData.getBoolean(STANDALONE_METADATA_NAME);
140             }
141         } catch (PackageManager.NameNotFoundException e) {
142             // Do nothing
143         }
144 
145         return false;
146     }
147 
148     /**
149      * Determines whether a given context has notification bridging enabled.
150      *
151      * @param context to be evaluated.
152      * @return Whether a given context has notification bridging enabled.
153      */
154     @SuppressWarnings("deprecation")
isNotificationBridgingEnabled(Context context)155     public static boolean isNotificationBridgingEnabled(Context context) {
156         try {
157             ApplicationInfo appInfo = context.getPackageManager().getApplicationInfo(
158                     context.getPackageName(), PackageManager.GET_META_DATA);
159             if (appInfo.metaData != null) {
160                 return NOTIFICATION_BRIDGE_MODE_BRIDGING.equals(
161                         appInfo.metaData.getString(NOTIFICATION_BRIDGE_MODE_METADATA_NAME));
162             }
163         } catch (PackageManager.NameNotFoundException e) {
164             // Do nothing
165         }
166 
167         return true;
168     }
169 
170     /**
171      *
172      * @param context to be evaluated.
173      * @param circular Whether to return the circular or regular preview.
174      *
175      * @return an integer id representing the resource id of the requested drawable, or 0 if
176      * no drawable was found.
177      */
178     @SuppressWarnings("deprecation")
getPreviewDrawableResourceId(Context context, boolean circular)179     public static int getPreviewDrawableResourceId(Context context, boolean circular) {
180         try {
181             ApplicationInfo appInfo = context.getPackageManager().getApplicationInfo(
182                     context.getPackageName(), PackageManager.GET_META_DATA);
183             if (appInfo.metaData != null) {
184                 return circular
185                         ?  appInfo.metaData.getInt(WATCH_FACE_PREVIEW_CIRCULAR_METADATA_NAME, 0)
186                         :  appInfo.metaData.getInt(WATCH_FACE_PREVIEW_METADATA_NAME, 0);
187             }
188         } catch (PackageManager.NameNotFoundException e) {
189             // Do nothing
190         }
191 
192         return 0;
193     }
194 
MetadataConstants()195     private MetadataConstants() {}
196 }
197