diff --git a/framework/src/org/apache/cordova/CordovaActivity.java b/framework/src/org/apache/cordova/CordovaActivity.java index 8e185dde..e1f917cd 100755 --- a/framework/src/org/apache/cordova/CordovaActivity.java +++ b/framework/src/org/apache/cordova/CordovaActivity.java @@ -268,6 +268,34 @@ public class CordovaActivity extends Activity { this.appView.handleResume(this.keepRunning); } + /** + * Called when the activity is no longer visible to the user. + */ + @Override + protected void onStop() { + super.onStop(); + LOG.d(TAG, "Stopped the activity."); + + if (this.appView == null) { + return; + } + this.appView.handleStop(); + } + + /** + * Called when the activity is becoming visible to the user. + */ + @Override + protected void onStart() { + super.onStart(); + LOG.d(TAG, "Started the activity."); + + if (this.appView == null) { + return; + } + this.appView.handleStart(); + } + /** * The final call you receive before your activity is destroyed. */ diff --git a/framework/src/org/apache/cordova/CordovaPlugin.java b/framework/src/org/apache/cordova/CordovaPlugin.java index 0d081178..7cf8528f 100644 --- a/framework/src/org/apache/cordova/CordovaPlugin.java +++ b/framework/src/org/apache/cordova/CordovaPlugin.java @@ -148,6 +148,18 @@ public class CordovaPlugin { public void onResume(boolean multitasking) { } + /** + * Called when the activity is becoming visible to the user. + */ + public void onStart() { + } + + /** + * Called when the activity is no longer visible to the user. + */ + public void onStop() { + } + /** * Called when the activity receives a new intent. */ diff --git a/framework/src/org/apache/cordova/CordovaWebView.java b/framework/src/org/apache/cordova/CordovaWebView.java index d3071f41..52dfb92c 100644 --- a/framework/src/org/apache/cordova/CordovaWebView.java +++ b/framework/src/org/apache/cordova/CordovaWebView.java @@ -61,6 +61,10 @@ public interface CordovaWebView { void handleResume(boolean keepRunning); + void handleStart(); + + void handleStop(); + void handleDestroy(); /** diff --git a/framework/src/org/apache/cordova/CordovaWebViewImpl.java b/framework/src/org/apache/cordova/CordovaWebViewImpl.java index 7115db41..868ad4f9 100644 --- a/framework/src/org/apache/cordova/CordovaWebViewImpl.java +++ b/framework/src/org/apache/cordova/CordovaWebViewImpl.java @@ -115,6 +115,7 @@ public class CordovaWebViewImpl implements CordovaWebView { pluginManager.addService(CoreAndroid.PLUGIN_NAME, "org.apache.cordova.CoreAndroid"); pluginManager.init(); + } @Override @@ -446,6 +447,20 @@ public class CordovaWebViewImpl implements CordovaWebView { this.pluginManager.onResume(keepRunning); sendJavascriptEvent("resume"); } + @Override + public void handleStart() { + if (!isInitialized()) { + return; + } + pluginManager.onStart(); + } + @Override + public void handleStop() { + if (!isInitialized()) { + return; + } + pluginManager.onStop(); + } @Override public void handleDestroy() { diff --git a/framework/src/org/apache/cordova/PluginManager.java b/framework/src/org/apache/cordova/PluginManager.java index 87663be9..a541e770 100755 --- a/framework/src/org/apache/cordova/PluginManager.java +++ b/framework/src/org/apache/cordova/PluginManager.java @@ -264,6 +264,28 @@ public class PluginManager { } } + /** + * Called when the activity is becoming visible to the user. + */ + public void onStart() { + for (CordovaPlugin plugin : this.pluginMap.values()) { + if (plugin != null) { + plugin.onStart(); + } + } + } + + /** + * Called when the activity is no longer visible to the user. + */ + public void onStop() { + for (CordovaPlugin plugin : this.pluginMap.values()) { + if (plugin != null) { + plugin.onStop(); + } + } + } + /** * The final call you receive before your activity is destroyed. */ diff --git a/test/androidTest/src/org/apache/cordova/test/CordovaPluginTest.java b/test/androidTest/src/org/apache/cordova/test/CordovaPluginTest.java new file mode 100644 index 00000000..f9f254aa --- /dev/null +++ b/test/androidTest/src/org/apache/cordova/test/CordovaPluginTest.java @@ -0,0 +1,70 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.cordova.test; + + +import android.app.Activity; +import android.test.ActivityInstrumentationTestCase2; + +import org.apache.cordova.CordovaWebView; + +import java.io.IOException; +import java.lang.reflect.Method; + +public class CordovaPluginTest extends BaseCordovaIntegrationTest { + + protected void setUp() throws Exception { + super.setUp(); + setUpWithStartUrl(null); + } + + private void invokeBlockingCallToLifeCycleEvent(final String lifeCycleEventName) { + testActivity.runOnUiThread( new Runnable() { + public void run() { + try { + Method method = getInstrumentation().getClass().getMethod(lifeCycleEventName, Activity.class); + method.invoke(getInstrumentation(), testActivity); + } catch (Exception e) { + fail("An Exception occurred in invokeBlockingCallToLifeCycleEvent while invoking " + lifeCycleEventName); + } + } + }); + getInstrumentation().waitForIdleSync(); + } + + public void testPluginLifeCycle() throws IOException { + //TODO: add coverage for both cases where handleOnStart is called in CordovaActivity (onStart and init) + //currently only one of the cases is covered + //TODO: add coverage for both cases where onStart is called in CordovaWebViewImpl (handleOnStart and init) + //currently only one of the cases is covered + LifeCyclePlugin testPlugin = (LifeCyclePlugin)cordovaWebView.getPluginManager().getPlugin("LifeCycle"); + + assertEquals("start,pause,stop,", testPlugin.calls); + testPlugin.calls = ""; + // testOnStart + invokeBlockingCallToLifeCycleEvent("callActivityOnStart"); + invokeBlockingCallToLifeCycleEvent("callActivityOnResume"); + invokeBlockingCallToLifeCycleEvent("callActivityOnPause"); + invokeBlockingCallToLifeCycleEvent("callActivityOnStop"); + assertEquals("start,resume,pause,stop,", testPlugin.calls); + } +} diff --git a/test/res/xml/config.xml b/test/res/xml/config.xml index 894c3362..7da46385 100644 --- a/test/res/xml/config.xml +++ b/test/res/xml/config.xml @@ -38,4 +38,8 @@ + + + + diff --git a/test/src/org/apache/cordova/test/LifeCyclePlugin.java b/test/src/org/apache/cordova/test/LifeCyclePlugin.java new file mode 100644 index 00000000..62ab7faa --- /dev/null +++ b/test/src/org/apache/cordova/test/LifeCyclePlugin.java @@ -0,0 +1,49 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +package org.apache.cordova.test; + +import org.apache.cordova.CordovaPlugin; +import org.apache.cordova.LOG; + +public class LifeCyclePlugin extends CordovaPlugin { + + static String TAG = "LifeCyclePlugin"; + String calls = ""; + + @Override + public void onStart() { + calls += "start,"; + LOG.d(TAG, "onStart"); + } + @Override + public void onPause(boolean multitasking) { + calls += "pause,"; + LOG.d(TAG, "onPause"); + } + @Override + public void onResume(boolean multitasking) { + calls += "resume,"; + LOG.d(TAG, "onResume"); + } + @Override + public void onStop() { + calls += "stop,"; + LOG.d(TAG, "onStop"); + } +}