diff --git a/android/titanium/src/java/org/appcelerator/titanium/TiBaseActivity.java b/android/titanium/src/java/org/appcelerator/titanium/TiBaseActivity.java
index 87ddf402c46..bff4735f135 100644
--- a/android/titanium/src/java/org/appcelerator/titanium/TiBaseActivity.java
+++ b/android/titanium/src/java/org/appcelerator/titanium/TiBaseActivity.java
@@ -72,7 +72,7 @@
* The base class for all non tab Titanium activities. To learn more about Activities, see the
* Android Activity documentation.
*/
-public abstract class TiBaseActivity extends AppCompatActivity
+public abstract class TiBaseActivity extends AppCompatActivity
implements TiActivitySupport/*, ITiWindowHandler*/
{
private static final String TAG = "TiBaseActivity";
@@ -94,7 +94,7 @@ public abstract class TiBaseActivity extends AppCompatActivity
public static KrollObject cameraCallbackContext, contactsCallbackContext, oldCalendarCallbackContext, calendarCallbackContext, locationCallbackContext;
public static KrollFunction cameraPermissionCallback, contactsPermissionCallback, oldCalendarPermissionCallback, calendarPermissionCallback, locationPermissionCallback;
-
+
protected View layout;
protected TiActivitySupportHelper supportHelper;
protected int supportHelperId = -1;
@@ -108,7 +108,7 @@ public abstract class TiBaseActivity extends AppCompatActivity
protected int msgActivityCreatedId = -1;
protected int msgId = -1;
protected static int previousOrientation = -1;
- //Storing the activity's dialogs and their persistence
+ //Storing the activity's dialogs and their persistence
private CopyOnWriteArrayList dialogs = new CopyOnWriteArrayList();
private Stack windowStack = new Stack();
@@ -122,13 +122,13 @@ public class DialogWrapper {
Dialog dialog;
WeakReference dialogActivity;
-
+
public DialogWrapper(Dialog d, boolean persistent, WeakReference activity) {
isPersistent = persistent;
dialog = d;
dialogActivity = activity;
}
-
+
public TiBaseActivity getActivity()
{
if (dialogActivity == null) {
@@ -146,12 +146,12 @@ public void setActivity(WeakReference da)
public Dialog getDialog() {
return dialog;
}
-
+
public void setDialog(Dialog d) {
dialog = d;
}
-
- public void release()
+
+ public void release()
{
dialog = null;
dialogActivity = null;
@@ -162,7 +162,7 @@ public boolean getPersistent()
return isPersistent;
}
- public void setPersistent(boolean p)
+ public void setPersistent(boolean p)
{
isPersistent = p;
}
@@ -208,7 +208,7 @@ public TiWindowProxy topWindowOnStack()
}
// could use a normal ConfigurationChangedListener but since only orientation changes are
- // forwarded, create a separate interface in order to limit scope and maintain clarity
+ // forwarded, create a separate interface in order to limit scope and maintain clarity
public static interface OrientationChangedListener
{
public void onOrientationChanged (int configOrientationMode);
@@ -256,7 +256,7 @@ public void setWindowProxy(TiWindowProxy proxy)
/**
* Sets the proxy for our layout (used for post layout event)
- *
+ *
* @param proxy
*/
public void setLayoutProxy(TiViewProxy proxy)
@@ -283,14 +283,14 @@ public ActivityProxy getActivityProxy()
return activityProxy;
}
- public void addDialog(DialogWrapper d)
+ public void addDialog(DialogWrapper d)
{
if (!dialogs.contains(d)) {
dialogs.add(d);
}
}
-
- public void removeDialog(Dialog d)
+
+ public void removeDialog(Dialog d)
{
for (int i = 0; i < dialogs.size(); i++) {
DialogWrapper p = dialogs.get(i);
@@ -419,17 +419,17 @@ protected View createLayout()
// set to null for now, this will get set correctly in setWindowProxy()
return new TiCompositeLayout(this, arrangement, null);
}
-
+
private void permissionCallback(int[] grantResults, KrollFunction callback, KrollObject context, String permission) {
if (callback == null) {
return;
}
boolean granted = true;
for (int i = 0; i < grantResults.length; ++i) {
- if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
- granted = false;
- break;
- }
+ if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
+ granted = false;
+ break;
+ }
}
if (granted) {
KrollDict response = new KrollDict();
@@ -486,13 +486,13 @@ protected void windowCreated(Bundle savedInstanceState)
int softInputMode = getIntentInt(TiC.PROPERTY_WINDOW_SOFT_INPUT_MODE, -1);
int windowFlags = getIntentInt(TiC.PROPERTY_WINDOW_FLAGS, 0);
boolean hasSoftInputMode = softInputMode != -1;
-
+
setFullscreen(fullscreen);
-
+
if (windowFlags > 0) {
getWindow().addFlags(windowFlags);
}
-
+
if (modal) {
if (Build.VERSION.SDK_INT < TiC.API_LEVEL_ICE_CREAM_SANDWICH) {
// This flag is deprecated in API 14. On ICS, the background is not blurred but straight black.
@@ -600,16 +600,16 @@ protected void onCreate(Bundle savedInstanceState)
if (theme != -1) {
this.setTheme(theme);
}
-
+
// Set ActionBar into split mode must be done before the decor view has been created
// we need to do this before calling super.onCreate()
if (intent != null && intent.hasExtra(TiC.PROPERTY_SPLIT_ACTIONBAR)) {
getWindow().setUiOptions(ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW);
}
-
+
// we only want to set the current activity for good in the resume state but we need it right now.
- // save off the existing current activity, set ourselves to be the new current activity temporarily
+ // save off the existing current activity, set ourselves to be the new current activity temporarily
// so we don't run into problems when we give the proxy the event
Activity tempCurrentActivity = tiApp.getCurrentActivity();
tiApp.setCurrentActivity(this, this);
@@ -618,7 +618,7 @@ protected void onCreate(Bundle savedInstanceState)
this.requestWindowFeature(Window.FEATURE_PROGRESS);
this.requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- this.requestWindowFeature(Window.FEATURE_ACTIVITY_TRANSITIONS);
+ this.requestWindowFeature(Window.FEATURE_ACTIVITY_TRANSITIONS);
}
super.onCreate(savedInstanceState);
@@ -710,7 +710,7 @@ public void run()
}
});
}
-
+
protected void handleSendMessage(int messageId)
{
try {
@@ -751,7 +751,7 @@ public void launchActivityForResult(Intent intent, int code, TiActivityResultHan
{
getSupportHelper().launchActivityForResult(intent, code, resultHandler);
}
-
+
/**
* See TiActivitySupport.launchIntentSenderForResult for more details.
*/
@@ -806,24 +806,24 @@ public void onBackPressed()
}
@Override
- public boolean dispatchKeyEvent(KeyEvent event)
+ public boolean dispatchKeyEvent(KeyEvent event)
{
boolean handled = false;
-
+
TiViewProxy window;
if (this.window != null) {
window = this.window;
} else {
window = this.view;
}
-
+
if (window == null) {
return super.dispatchKeyEvent(event);
}
switch(event.getKeyCode()) {
case KeyEvent.KEYCODE_BACK : {
-
+
if (event.getAction() == KeyEvent.ACTION_UP) {
String backEvent = "android:back";
KrollProxy proxy = null;
@@ -835,12 +835,12 @@ public boolean dispatchKeyEvent(KeyEvent event)
} else if (window.hasListeners(backEvent)) {
proxy = window;
}
-
+
if (proxy != null) {
proxy.fireEvent(backEvent, null);
handled = true;
}
-
+
}
break;
}
@@ -930,7 +930,7 @@ public boolean dispatchKeyEvent(KeyEvent event)
break;
}
}
-
+
if (!handled) {
handled = super.dispatchKeyEvent(event);
}
@@ -941,7 +941,7 @@ public boolean dispatchKeyEvent(KeyEvent event)
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
- // If targetSdkVersion is set to 11+, Android will invoke this function
+ // If targetSdkVersion is set to 11+, Android will invoke this function
// to initialize the menu (since it's part of the action bar). Due
// to the fix for Android bug 2373, activityProxy won't be initialized b/c the
// activity is expected to restart, so we will ignore it.
@@ -1030,7 +1030,7 @@ public void onConfigurationChanged(Configuration newConfig)
}
@Override
- protected void onNewIntent(Intent intent)
+ protected void onNewIntent(Intent intent)
{
super.onNewIntent(intent);
@@ -1093,7 +1093,15 @@ private void dispatchCallback(String name, KrollDict data) {
data.put("source", activityProxy);
- activityProxy.callPropertyAsync(name, new Object[] { data });
+ // TIMOB-19903
+ if (TiApplication.getInstance().runOnMainThread()) {
+ // We must call this synchornously to ensure it happens before we release the Activity reference on the V8/Native side!
+ activityProxy.callPropertySync(name, new Object[] { data });
+ } else {
+ // This hopefully finishes before we release the reference on the native side?! I have seen it crash because it didn't before though...
+ // Not sure it's safe to keep this behavior...
+ activityProxy.callPropertyAsync(name, new Object[] { data });
+ }
}
private void releaseDialogs(boolean finish)
@@ -1135,7 +1143,7 @@ public void onWindowFocusChanged(boolean hasFocus)
* When this activity pauses, this method sets the current activity to null, fires a javascript 'pause' event,
* and if the activity is finishing, remove all dialogs associated with it.
*/
- protected void onPause()
+ protected void onPause()
{
inForeground = false;
if (activityProxy != null) {
@@ -1158,7 +1166,7 @@ protected void onPause()
if (!windowStack.empty()) {
windowStack.peek().onWindowFocusChange(false);
}
-
+
TiApplication.updateActivityTransitionState(true);
tiApp.setCurrentActivity(this, null);
TiUIHelper.showSoftKeyboard(getWindow().getDecorView(), false);
@@ -1219,11 +1227,11 @@ protected void onResume()
if (!windowStack.empty()) {
windowStack.peek().onWindowFocusChange(true);
- }
-
+ }
+
tiApp.setCurrentActivity(this, this);
TiApplication.updateActivityTransitionState(false);
-
+
if (activityProxy != null) {
activityProxy.fireEvent(TiC.EVENT_RESUME, null);
}
@@ -1251,7 +1259,7 @@ protected void onResume()
@Override
/**
* When this activity starts, this method updates the current activity to this if necessary and
- * fire javascript 'start' and 'focus' events. Focus events will only fire if
+ * fire javascript 'start' and 'focus' events. Focus events will only fire if
* the activity is not a tab activity.
*/
protected void onStart()
@@ -1284,7 +1292,7 @@ protected void onStart()
if (activityProxy != null) {
// we only want to set the current activity for good in the resume state but we need it right now.
- // save off the existing current activity, set ourselves to be the new current activity temporarily
+ // save off the existing current activity, set ourselves to be the new current activity temporarily
// so we don't run into problems when we give the proxy the event
Activity tempCurrentActivity = tiApp.getCurrentActivity();
tiApp.setCurrentActivity(this, this);
@@ -1306,7 +1314,7 @@ protected void onStart()
}
}
// store current configuration orientation
- // This fixed bug with double orientation chnage firing when activity starts in landscape
+ // This fixed bug with double orientation chnage firing when activity starts in landscape
previousOrientation = getWindowManager().getDefaultDisplay().getRotation();
}
@@ -1363,7 +1371,7 @@ protected void onRestart()
super.onRestart();
Log.d(TAG, "Activity " + this + " onRestart", Log.DEBUG_MODE);
-
+
TiApplication tiApp = getTiApp();
if (tiApp.isRestartPending()) {
if (!isFinishing()) {
@@ -1375,7 +1383,7 @@ protected void onRestart()
if (activityProxy != null) {
// we only want to set the current activity for good in the resume state but we need it right now.
- // save off the existing current activity, set ourselves to be the new current activity temporarily
+ // save off the existing current activity, set ourselves to be the new current activity temporarily
// so we don't run into problems when we give the proxy the event
Activity tempCurrentActivity = tiApp.getCurrentActivity();
tiApp.setCurrentActivity(this, this);
@@ -1389,7 +1397,7 @@ protected void onRestart()
@Override
/**
- * When the activity is about to go into the background as a result of user choice, this method fires the
+ * When the activity is about to go into the background as a result of user choice, this method fires the
* javascript 'userleavehint' event.
*/
protected void onUserLeaveHint()
@@ -1409,11 +1417,11 @@ protected void onUserLeaveHint()
super.onUserLeaveHint();
}
-
+
@Override
/**
* When this activity is destroyed, this method removes it from the activity stack, performs
- * clean up, and fires javascript 'destroy' event.
+ * clean up, and fires javascript 'destroy' event.
*/
protected void onDestroy()
{
@@ -1424,7 +1432,7 @@ protected void onDestroy()
inForeground = false;
TiApplication tiApp = getTiApp();
- //Clean up dialogs when activity is destroyed.
+ //Clean up dialogs when activity is destroyed.
releaseDialogs(true);
if (tiApp.isRestartPending()) {
@@ -1639,4 +1647,3 @@ public static boolean isUnsupportedReLaunch(Activity activity, Bundle savedInsta
return false;
}
}
-