5252
5353import static android .content .pm .ApplicationInfo .FLAG_DEBUGGABLE ;
5454import static android .util .Log .VERBOSE ;
55+ import static com .microsoft .appcenter .ApplicationContextUtils .getApplicationContext ;
56+ import static com .microsoft .appcenter .ApplicationContextUtils .isDeviceProtectedStorage ;
5557import static com .microsoft .appcenter .Constants .DEFAULT_TRIGGER_COUNT ;
5658import static com .microsoft .appcenter .Constants .DEFAULT_TRIGGER_INTERVAL ;
5759import static com .microsoft .appcenter .Constants .DEFAULT_TRIGGER_MAX_PARALLEL_REQUESTS ;
@@ -135,10 +137,18 @@ public class AppCenter {
135137 private String mLogUrl ;
136138
137139 /**
138- * Application context.
140+ * Android application object that was passed during configuration.
141+ * It shouldn't be used directly, but only for getting right context.
142+ * It's null until SDK is configured.
139143 */
140144 private Application mApplication ;
141145
146+ /**
147+ * Application context. Might be special context with device-protected storage.
148+ * See {@link ApplicationContextUtils#getApplicationContext(Application)}.
149+ */
150+ private Context mContext ;
151+
142152 /**
143153 * Application lifecycle listener.
144154 */
@@ -710,8 +720,20 @@ public void run() {
710720 return true ;
711721 }
712722
713- /* Store state . */
723+ /* Store application to use it later for registering services as lifecycle callbacks . */
714724 mApplication = application ;
725+ mContext = getApplicationContext (application );
726+ if (isDeviceProtectedStorage (mContext )) {
727+
728+ /*
729+ * In this mode storing sensitive is strongly discouraged, but App Center considers regular storage as
730+ * not secure as well, so all tokens are encrypted separately anyway. Just warn about it.
731+ */
732+ AppCenterLog .warn (LOG_TAG ,
733+ "A user is locked, credential-protected private app data storage is not available.\n " +
734+ "App Center will use device-protected data storage that available without user authentication.\n " +
735+ "Please note that it's a separate storage, all settings and pending logs won't be shared with regular storage." );
736+ }
715737
716738 /* Start looper. */
717739 mHandlerThread = new HandlerThread ("AppCenter.Looper" );
@@ -825,11 +847,11 @@ public void run() {
825847 private void finishConfiguration (boolean configureFromApp ) {
826848
827849 /* Load some global constants. */
828- Constants .loadFromContext (mApplication );
850+ Constants .loadFromContext (mContext );
829851
830852 /* If parameters are valid, init context related resources. */
831- FileManager .initialize (mApplication );
832- SharedPreferencesManager .initialize (mApplication );
853+ FileManager .initialize (mContext );
854+ SharedPreferencesManager .initialize (mContext );
833855
834856 /* Set network requests allowed. */
835857 if (mAllowedNetworkRequests != null ) {
@@ -845,13 +867,13 @@ private void finishConfiguration(boolean configureFromApp) {
845867 /* Instantiate HTTP client if it doesn't exist as a dependency. */
846868 HttpClient httpClient = DependencyConfiguration .getHttpClient ();
847869 if (httpClient == null ) {
848- httpClient = createHttpClient (mApplication );
870+ httpClient = createHttpClient (mContext );
849871 }
850872
851873 /* Init channel. */
852874 mLogSerializer = new DefaultLogSerializer ();
853875 mLogSerializer .addLogFactory (StartServiceLog .TYPE , new StartServiceLogFactory ());
854- mChannel = new DefaultChannel (mApplication , mAppSecret , mLogSerializer , httpClient , mHandler );
876+ mChannel = new DefaultChannel (mContext , mAppSecret , mLogSerializer , httpClient , mHandler );
855877
856878 /* Complete set maximum storage size future if starting from app. */
857879 if (configureFromApp ) {
@@ -877,7 +899,7 @@ private void finishConfiguration(boolean configureFromApp) {
877899
878900 /* Disable listening network if we start while being disabled. */
879901 if (!enabled ) {
880- NetworkStateHelper .getSharedInstance (mApplication ).close ();
902+ NetworkStateHelper .getSharedInstance (mContext ).close ();
881903 }
882904
883905 /* Init uncaught exception handler. */
@@ -902,7 +924,7 @@ private final synchronized void startServices(final boolean startFromApp, Class<
902924 AppCenterLog .error (LOG_TAG , "Cannot start services, services array is null. Failed to start services." );
903925 return ;
904926 }
905- if (mApplication == null ) {
927+ if (! isInstanceConfigured () ) {
906928 StringBuilder serviceNames = new StringBuilder ();
907929 for (Class <? extends AppCenterService > service : services ) {
908930 serviceNames .append ("\t " ).append (service .getName ()).append ("\n " );
@@ -1011,10 +1033,10 @@ private void finishStartServices(Iterable<AppCenterService> updatedServices, Ite
10111033 service .setInstanceEnabled (false );
10121034 }
10131035 if (startFromApp ) {
1014- service .onStarted (mApplication , mChannel , mAppSecret , mTransmissionTargetToken , true );
1036+ service .onStarted (mContext , mChannel , mAppSecret , mTransmissionTargetToken , true );
10151037 AppCenterLog .info (LOG_TAG , service .getClass ().getSimpleName () + " service started from application." );
10161038 } else {
1017- service .onStarted (mApplication , mChannel , null , null , false );
1039+ service .onStarted (mContext , mChannel , null , null , false );
10181040 AppCenterLog .info (LOG_TAG , service .getClass ().getSimpleName () + " service started from library." );
10191041 }
10201042 }
@@ -1118,10 +1140,10 @@ private void setInstanceEnabled(boolean enabled) {
11181140 /* Update uncaught exception subscription. */
11191141 if (switchToEnabled ) {
11201142 mUncaughtExceptionHandler .register ();
1121- NetworkStateHelper .getSharedInstance (mApplication ).reopen ();
1143+ NetworkStateHelper .getSharedInstance (mContext ).reopen ();
11221144 } else if (switchToDisabled ) {
11231145 mUncaughtExceptionHandler .unregister ();
1124- NetworkStateHelper .getSharedInstance (mApplication ).close ();
1146+ NetworkStateHelper .getSharedInstance (mContext ).close ();
11251147 }
11261148
11271149 /* Update state now if true, services are checking this. */
0 commit comments