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");
+ }
+}