1616import android .util .Log ;
1717
1818import com .deploygate .sdk .internal .Logger ;
19+ import com .deploygate .sdk .internal .VisibilityLifecycleCallbacks ;
1920import com .deploygate .service .DeployGateEvent ;
2021import com .deploygate .service .IDeployGateSdkService ;
2122import com .deploygate .service .IDeployGateSdkServiceCallback ;
2223
24+ import java .util .HashMap ;
2325import java .util .HashSet ;
26+ import java .util .Iterator ;
2427import java .util .LinkedList ;
28+ import java .util .Map ;
2529import java .util .concurrent .CountDownLatch ;
30+ import java .util .concurrent .TimeUnit ;
2631
2732/**
2833 * This is DeployGate SDK library. Import this library to the application
@@ -42,6 +47,7 @@ public class DeployGate {
4247
4348 private static final String ACTION_DEPLOYGATE_STARTED = "com.deploygate.action.ServiceStarted" ;
4449 private static final String DEPLOYGATE_PACKAGE = "com.deploygate" ;
50+ private static final Object sPendingEventLock = new Object ();
4551
4652 private static DeployGate sInstance ;
4753
@@ -52,6 +58,7 @@ public class DeployGate {
5258 private final ILogcatInstructionSerializer mLogcatInstructionSerializer ;
5359 private final CustomLogInstructionSerializer mCustomLogInstructionSerializer ;
5460 private final HashSet <DeployGateCallback > mCallbacks ;
61+ private final HashMap <String , Bundle > mPendingEvents ;
5562 private final String mExpectedAuthor ;
5663 private String mAuthor ;
5764
@@ -85,12 +92,22 @@ public void onEvent(
8592 return ;
8693 }
8794
95+ // ensure non-null
96+ extras = extras != null ? extras : new Bundle ();
97+
8898 if (DeployGateEvent .ACTION_INIT .equals (action )) {
8999 onInitialized (extras .getBoolean (DeployGateEvent .EXTRA_IS_MANAGED , false ), extras .getBoolean (DeployGateEvent .EXTRA_IS_AUTHORIZED , false ), extras .getString (DeployGateEvent .EXTRA_LOGIN_USERNAME ), extras .getString (DeployGateEvent .EXTRA_DISTRIBUTION_USER_NAME ), extras .getBoolean (DeployGateEvent .EXTRA_IS_STOP_REQUESTED , false ), extras .getString (DeployGateEvent .EXTRA_AUTHOR ), extras .getInt (DeployGateEvent .EXTRA_CURRENT_REVISION , 0 ), extras .getString (DeployGateEvent .EXTRA_CURRENT_DISTRIBUTION_ID ), extras .getString (DeployGateEvent .EXTRA_CURRENT_DISTRIBUTION_TITLE ));
90100 } else if (DeployGateEvent .ACTION_UPDATE_AVAILABLE .equals (action )) {
91101 onUpdateArrived (extras .getInt (DeployGateEvent .EXTRA_SERIAL ), extras .getString (DeployGateEvent .EXTRA_VERSION_NAME ), extras .getInt (DeployGateEvent .EXTRA_VERSION_CODE ), extras .getString (DeployGateEvent .EXTRA_SERIAL_MESSAGE ));
92102 } else if (DeployGateEvent .ACTION_ONESHOT_LOGCAT .equals (action )) {
93- onOneshotLogcat ();
103+ String captureId = null ;
104+
105+ if (mDeployGateClient .isSupported (Compatibility .DEVICE_CAPTURE )) {
106+ // still nullable
107+ captureId = extras .getString (DeployGateEvent .EXTRA_CAPTURE_ID );
108+ }
109+
110+ onOneshotLogcat (captureId );
94111 } else if (DeployGateEvent .ACTION_ENABLE_LOGCAT .equals (action )) {
95112 if (mDeployGateClient .isSupported (Compatibility .STREAMED_LOGCAT )) {
96113 String sessionKey = extras .getString (DeployGateEvent .EXTRA_LOGCAT_STREAM_SESSION_KEY );
@@ -110,6 +127,8 @@ public void onEvent(
110127 } else {
111128 Logger .w ("streamed logcat is not supported" );
112129 }
130+ } else {
131+ Logger .w ("%s is not supported by this sdk version" , action );
113132 }
114133 }
115134
@@ -153,6 +172,9 @@ public void run() {
153172 mLogcatInstructionSerializer .connect (mRemoteService );
154173
155174 mInitializedLatch .countDown ();
175+
176+ // to release a lock as soon as possible.
177+ flushPendingEvents ();
156178 }
157179
158180 private void onUpdateArrived (
@@ -178,12 +200,38 @@ public void run() {
178200 }
179201 };
180202
203+ @ SuppressWarnings ("FieldCanBeLocal" )
204+ private final VisibilityLifecycleCallbacks .OnVisibilityChangeListener mOnVisibilityChangeListener = new VisibilityLifecycleCallbacks .OnVisibilityChangeListener () {
205+
206+ @ Override
207+ public void onForeground (
208+ long elapsedRealtime ,
209+ TimeUnit timeUnit
210+ ) {
211+ Bundle extras = new Bundle ();
212+ extras .putLong (DeployGateEvent .EXTRA_VISIBILITY_EVENT_ELAPSED_REAL_TIME_IN_NANOS , timeUnit .toNanos (elapsedRealtime ));
213+ extras .putInt (DeployGateEvent .EXTRA_VISIBILITY_EVENT_TYPE , DeployGateEvent .VisibilityType .FOREGROUND );
214+ invokeAction (DeployGateEvent .ACTION_VISIBILITY_EVENT , extras , true );
215+ }
216+
217+ @ Override
218+ public void onBackground (
219+ long elapsedRealtime ,
220+ TimeUnit timeUnit
221+ ) {
222+ Bundle extras = new Bundle ();
223+ extras .putLong (DeployGateEvent .EXTRA_VISIBILITY_EVENT_ELAPSED_REAL_TIME_IN_NANOS , timeUnit .toNanos (elapsedRealtime ));
224+ extras .putInt (DeployGateEvent .EXTRA_VISIBILITY_EVENT_TYPE , DeployGateEvent .VisibilityType .BACKGROUND );
225+ invokeAction (DeployGateEvent .ACTION_VISIBILITY_EVENT , extras , true );
226+ }
227+ };
228+
181229 private void requestOneshotLogcat () {
182- onOneshotLogcat ();
230+ onOneshotLogcat (null );
183231 }
184232
185- private void onOneshotLogcat () {
186- mLogcatInstructionSerializer .requestOneshotLogcat ();
233+ private void onOneshotLogcat (String captureId ) {
234+ mLogcatInstructionSerializer .requestOneshotLogcat (captureId );
187235 }
188236
189237 private void onEnableStreamedLogcat (String streamSessionKey ) {
@@ -229,7 +277,8 @@ private DeployGate(
229277 mHandler = new Handler ();
230278 mLogcatInstructionSerializer = mHostApp .canUseLogcat ? new LogcatInstructionSerializer (mHostApp .packageName ) : ILogcatInstructionSerializer .NULL_INSTANCE ;
231279 mCustomLogInstructionSerializer = new CustomLogInstructionSerializer (mHostApp .packageName , customLogConfiguration );
232- mCallbacks = new HashSet <DeployGateCallback >();
280+ mCallbacks = new HashSet <>();
281+ mPendingEvents = new HashMap <>();
233282 mExpectedAuthor = author ;
234283
235284 prepareBroadcastReceiver ();
@@ -239,6 +288,7 @@ private DeployGate(
239288 }
240289
241290 mInitializedLatch = new CountDownLatch (1 );
291+ ((Application ) applicationContext ).registerActivityLifecycleCallbacks (new VisibilityLifecycleCallbacks (mOnVisibilityChangeListener ));
242292 initService (true );
243293 }
244294
@@ -318,11 +368,30 @@ private void requestServiceInit(final boolean isBoot) {
318368 }
319369 }
320370
371+ /**
372+ * Send an event to the client application
373+ *
374+ * @param action
375+ * to be sent
376+ * @param extras
377+ * to be sent
378+ * @param allowPending
379+ * Allow queueing events to send them after a service connection is established (since 4.6.0)
380+ */
321381 private void invokeAction (
322382 String action ,
323- Bundle extras
383+ Bundle extras ,
384+ boolean allowPending
324385 ) {
386+ extras = extras != null ? extras : new Bundle ();
387+
325388 if (mRemoteService == null ) {
389+ if (allowPending ) {
390+ synchronized (sPendingEventLock ) {
391+ mPendingEvents .put (action , extras );
392+ }
393+ }
394+
326395 return ;
327396 }
328397 try {
@@ -332,6 +401,19 @@ private void invokeAction(
332401 }
333402 }
334403
404+ private void flushPendingEvents () {
405+ // cannot re-enqueue events for now
406+ synchronized (sPendingEventLock ) {
407+ Iterator <Map .Entry <String , Bundle >> iterator = mPendingEvents .entrySet ().iterator ();
408+
409+ while (iterator .hasNext ()) {
410+ Map .Entry <String , Bundle > entry = iterator .next ();
411+ invokeAction (entry .getKey (), entry .getValue (), false );
412+ iterator .remove ();
413+ }
414+ }
415+ }
416+
335417 /**
336418 * Clear the initiated DeployGate instance.
337419 * <p>
@@ -1191,7 +1273,7 @@ public static void installUpdate() {
11911273 return ;
11921274 }
11931275
1194- sInstance .invokeAction (DeployGateEvent .ACTION_INSTALL_UPDATE , null );
1276+ sInstance .invokeAction (DeployGateEvent .ACTION_INSTALL_UPDATE , null , false );
11951277 }
11961278
11971279 /**
@@ -1207,7 +1289,7 @@ public static void openComments() {
12071289 return ;
12081290 }
12091291
1210- sInstance .invokeAction (DeployGateEvent .ACTION_OPEN_COMMENTS , null );
1292+ sInstance .invokeAction (DeployGateEvent .ACTION_OPEN_COMMENTS , null , false );
12111293 }
12121294
12131295 /**
@@ -1240,7 +1322,7 @@ public static void composeComment(String defaultComment) {
12401322
12411323 Bundle extras = new Bundle ();
12421324 extras .putString (DeployGateEvent .EXTRA_COMMENT , defaultComment );
1243- sInstance .invokeAction (DeployGateEvent .ACTION_COMPOSE_COMMENT , extras );
1325+ sInstance .invokeAction (DeployGateEvent .ACTION_COMPOSE_COMMENT , extras , false );
12441326 }
12451327
12461328 /**
0 commit comments