2323import java .io .RandomAccessFile ;
2424import java .io .UnsupportedEncodingException ;
2525import java .util .ArrayList ;
26+ import java .util .Collection ;
27+ import java .util .Collections ;
2628import java .util .HashSet ;
2729import java .util .List ;
2830import java .util .Set ;
3537 * library.
3638 */
3739public class Parse {
40+ /**
41+ * Represents an opaque configuration for the {@code Parse} SDK configuration.
42+ */
43+ public static final class Configuration {
44+ /**
45+ * Allows for simple constructing of a {@code Configuration} object.
46+ */
47+ public static final class Builder {
48+ private Context context ;
49+ private String applicationId ;
50+ private String clientKey ;
51+ private boolean localDataStoreEnabled ;
52+ private List <ParseNetworkInterceptor > interceptors ;
53+
54+ /**
55+ * Initialize a bulider with a given context.
56+ *
57+ * This context will then be passed through to the rest of the Parse SDK for use during
58+ * initialization.
59+ *
60+ * <p/>
61+ * You may define {@code com.parse.APPLICATION_ID} and {@code com.parse.CLIENT_KEY}
62+ * {@code meta-data} in your {@code AndroidManifest.xml}:
63+ * <pre>
64+ * <manifest ...>
65+ *
66+ * ...
67+ *
68+ * <application ...>
69+ * <meta-data
70+ * android:name="com.parse.APPLICATION_ID"
71+ * android:value="@string/parse_app_id" />
72+ * <meta-data
73+ * android:name="com.parse.CLIENT_KEY"
74+ * android:value="@string/parse_client_key" />
75+ *
76+ * ...
77+ *
78+ * </application>
79+ * </manifest>
80+ * </pre>
81+ * <p/>
82+ *
83+ * This will cause the values for {@code applicationId} and {@code clientKey} to be set to
84+ * those defined in your manifest.
85+ *
86+ * @param context The active {@link Context} for your application. Cannot be null.
87+ */
88+ public Builder (Context context ) {
89+ this .context = context ;
90+
91+ // Yes, our public API states we cannot be null. But for unit tests, it's easier just to
92+ // support null here.
93+ if (context != null ) {
94+ Context applicationContext = context .getApplicationContext ();
95+ Bundle metaData = ManifestInfo .getApplicationMetadata (applicationContext );
96+ if (metaData != null ) {
97+ applicationId = metaData .getString (PARSE_APPLICATION_ID );
98+ clientKey = metaData .getString (PARSE_CLIENT_KEY );
99+ }
100+ }
101+ }
102+
103+ /**
104+ * Set the application id to be used by Parse.
105+ *
106+ * This method is only required if you intend to use a different {@code applicationId} than
107+ * is defined by {@code com.parse.APPLICATION_ID} in your {@code AndroidManifest.xml}.
108+ *
109+ * @param applicationId The application id to set.
110+ * @return The same builder, for easy chaining.
111+ */
112+ public Builder applicationId (String applicationId ) {
113+ this .applicationId = applicationId ;
114+ return this ;
115+ }
116+
117+ /**
118+ * Set the client key to be used by Parse.
119+ *
120+ * This method is only required if you intend to use a different {@code clientKey} than
121+ * is defined by {@code com.parse.CLIENT_KEY} in your {@code AndroidManifest.xml}.
122+ *
123+ * @param clientKey The client key to set.
124+ * @return The same builder, for easy chaining.
125+ */
126+ public Builder clientKey (String clientKey ) {
127+ this .clientKey = clientKey ;
128+ return this ;
129+ }
130+
131+ /**
132+ * Add a {@link ParseNetworkInterceptor}.
133+ *
134+ * @param interceptor The interceptor to add.
135+ * @return The same builder, for easy chaining.
136+ */
137+ public Builder addNetworkInterceptor (ParseNetworkInterceptor interceptor ) {
138+ if (interceptors == null ) {
139+ interceptors = new ArrayList <>();
140+ }
141+ interceptors .add (interceptor );
142+ return this ;
143+ }
144+
145+ /**
146+ * Enable pinning in your application. This must be called before your application can use
147+ * pinning.
148+ * @return The same builder, for easy chaining.
149+ */
150+ public Builder enableLocalDataStore () {
151+ localDataStoreEnabled = true ;
152+ return this ;
153+ }
154+
155+ private Builder setNetworkInterceptors (Collection <ParseNetworkInterceptor > interceptors ) {
156+ if (interceptors != null ) {
157+ this .interceptors .clear ();
158+ this .interceptors .addAll (interceptors );
159+ }
160+ return this ;
161+ }
162+
163+ private Builder setLocalDatastoreEnabled (boolean enabled ) {
164+ localDataStoreEnabled = enabled ;
165+ return this ;
166+ }
167+
168+ /**
169+ * Construct this builder into a concrete {@code Configuration} instance.
170+ * @return A constructed {@code Configuration} object.
171+ */
172+ public Configuration build () {
173+ return new Configuration (this );
174+ }
175+ }
176+
177+ /* package for tests */ final Context context ;
178+ /* package for tests */ final String applicationId ;
179+ /* package for tests */ final String clientKey ;
180+ /* package for tests */ final boolean localDataStoreEnabled ;
181+ /* package for tests */ final List <ParseNetworkInterceptor > interceptors ;
182+
183+ private Configuration (Builder builder ) {
184+ this .context = builder .context ;
185+ this .applicationId = builder .applicationId ;
186+ this .clientKey = builder .clientKey ;
187+ this .localDataStoreEnabled = builder .localDataStoreEnabled ;
188+ this .interceptors = builder .interceptors != null ?
189+ Collections .unmodifiableList (new ArrayList <>(builder .interceptors )) :
190+ null ;
191+ }
192+ }
193+
38194 private static final String PARSE_APPLICATION_ID = "com.parse.APPLICATION_ID" ;
39195 private static final String PARSE_CLIENT_KEY = "com.parse.CLIENT_KEY" ;
40196
@@ -133,32 +289,24 @@ public static void enableLocalDatastore(Context context) {
133289 * The active {@link Context} for your application.
134290 */
135291 public static void initialize (Context context ) {
136- Context applicationContext = context .getApplicationContext ();
137- String applicationId ;
138- String clientKey ;
139- Bundle metaData = ManifestInfo .getApplicationMetadata (applicationContext );
140- if (metaData != null ) {
141- applicationId = metaData .getString (PARSE_APPLICATION_ID );
142- clientKey = metaData .getString (PARSE_CLIENT_KEY );
143-
144- if (applicationId == null ) {
145- throw new RuntimeException ("ApplicationId not defined. " +
146- "You must provide ApplicationId in AndroidManifest.xml.\n " +
147- "<meta-data\n " +
148- " android:name=\" com.parse.APPLICATION_ID\" \n " +
149- " android:value=\" <Your Application Id>\" />" );
150- }
151- if (clientKey == null ) {
152- throw new RuntimeException ("ClientKey not defined. " +
153- "You must provide ClientKey in AndroidManifest.xml.\n " +
154- "<meta-data\n " +
155- " android:name=\" com.parse.CLIENT_KEY\" \n " +
156- " android:value=\" <Your Client Key>\" />" );
157- }
158- } else {
159- throw new RuntimeException ("Can't get Application Metadata" );
292+ Configuration .Builder builder = new Configuration .Builder (context );
293+ if (builder .applicationId == null ) {
294+ throw new RuntimeException ("ApplicationId not defined. " +
295+ "You must provide ApplicationId in AndroidManifest.xml.\n " +
296+ "<meta-data\n " +
297+ " android:name=\" com.parse.APPLICATION_ID\" \n " +
298+ " android:value=\" <Your Application Id>\" />" );
299+ } if (builder .clientKey == null ) {
300+ throw new RuntimeException ("ClientKey not defined. " +
301+ "You must provide ClientKey in AndroidManifest.xml.\n " +
302+ "<meta-data\n " +
303+ " android:name=\" com.parse.CLIENT_KEY\" \n " +
304+ " android:value=\" <Your Client Key>\" />" );
160305 }
161- initialize (context , applicationId , clientKey );
306+ initialize (builder .setNetworkInterceptors (interceptors )
307+ .setLocalDatastoreEnabled (isLocalDatastoreEnabled )
308+ .build ()
309+ );
162310 }
163311
164312 /**
@@ -188,22 +336,36 @@ public static void initialize(Context context) {
188336 * The client key provided in the Parse dashboard.
189337 */
190338 public static void initialize (Context context , String applicationId , String clientKey ) {
191- ParsePlugins .Android .initialize (context , applicationId , clientKey );
192- Context applicationContext = context .getApplicationContext ();
339+ initialize (new Configuration .Builder (context )
340+ .applicationId (applicationId )
341+ .clientKey (clientKey )
342+ .setNetworkInterceptors (interceptors )
343+ .setLocalDatastoreEnabled (isLocalDatastoreEnabled )
344+ .build ()
345+ );
346+ }
347+
348+ public static void initialize (Configuration configuration ) {
349+ // NOTE (richardross): We will need this here, as ParsePlugins uses the return value of
350+ // isLocalDataStoreEnabled() to perform additional behavior.
351+ isLocalDatastoreEnabled = configuration .localDataStoreEnabled ;
352+
353+ ParsePlugins .Android .initialize (configuration .context , configuration .applicationId , configuration .clientKey );
354+ Context applicationContext = configuration .context .getApplicationContext ();
193355
194356 ParseHttpClient .setKeepAlive (true );
195357 ParseHttpClient .setMaxConnections (20 );
196358 // If we have interceptors in list, we have to initialize all http clients and add interceptors
197- if (interceptors != null ) {
198- initializeParseHttpClientsWithParseNetworkInterceptors ();
359+ if (configuration . interceptors != null ) {
360+ initializeParseHttpClientsWithParseNetworkInterceptors (configuration . interceptors );
199361 }
200362
201363 ParseObject .registerParseSubclasses ();
202364
203- if (isLocalDatastoreEnabled () ) {
204- offlineStore = new OfflineStore (context );
365+ if (configuration . localDataStoreEnabled ) {
366+ offlineStore = new OfflineStore (configuration . context );
205367 } else {
206- ParseKeyValueCache .initialize (context );
368+ ParseKeyValueCache .initialize (configuration . context );
207369 }
208370
209371 // Make sure the data on disk for Parse is for the current
@@ -583,7 +745,7 @@ private Parse() {
583745 private static List <ParseNetworkInterceptor > interceptors ;
584746
585747 // Initialize all necessary http clients and add interceptors to these http clients
586- private static void initializeParseHttpClientsWithParseNetworkInterceptors () {
748+ private static void initializeParseHttpClientsWithParseNetworkInterceptors (List < ParseNetworkInterceptor > interceptors ) {
587749 // This means developers have not called addInterceptor method so we should do nothing.
588750 if (interceptors == null ) {
589751 return ;
@@ -605,9 +767,6 @@ private static void initializeParseHttpClientsWithParseNetworkInterceptors() {
605767 parseHttpClient .addExternalInterceptor (interceptor );
606768 }
607769 }
608-
609- // Remove interceptors reference since we do not need it anymore
610- interceptors = null ;
611770 }
612771
613772
0 commit comments