feat: add androidx support (#901)

This commit is contained in:
エリス 2020-01-27 15:52:08 +09:00 committed by GitHub
parent 92268b2e76
commit d01ed80a61
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
103 changed files with 4735 additions and 23 deletions

View File

@ -1,2 +1,3 @@
bin/templates/project/assets/www/cordova.js
test/app
test/android/app
test/androidx/app

11
.gitignore vendored
View File

@ -26,9 +26,14 @@ example
/framework/javadoc-public
/framework/javadoc-private
/test/.externalNativeBuild
/test/gradle
/test/gradlew
/test/gradlew.bat
/test/android/gradle
/test/android/gradlew
/test/android/gradlew.bat
/test/androidx/gradle
/test/androidx/gradlew
/test/androidx/gradlew.bat
/test/assets/www/.tmp*
/test/assets/www/cordova.js
/test/bin

View File

@ -34,7 +34,11 @@ class GradlePropertiesParser {
'org.gradle.daemon': 'true',
// to allow dex in process
'org.gradle.jvmargs': '-Xmx2048m'
'org.gradle.jvmargs': '-Xmx2048m',
// Android X
'android.useAndroidX': 'true',
'android.enableJetifier': 'true'
// Shaves another 100ms, but produces a "try at own risk" warning. Not worth it (yet):
// 'org.gradle.parallel': 'true'

View File

@ -45,12 +45,19 @@ module.exports.prepare = function (cordovaProject, options) {
const minSdkVersion = this._config.getPreference('android-minSdkVersion', 'android');
const maxSdkVersion = this._config.getPreference('android-maxSdkVersion', 'android');
const targetSdkVersion = this._config.getPreference('android-targetSdkVersion', 'android');
const androidXEnabled = this._config.getPreference('AndroidXEnabled', 'android');
let gradlePropertiesUserConfig = {};
if (minSdkVersion) gradlePropertiesUserConfig.cdvMinSdkVersion = minSdkVersion;
if (maxSdkVersion) gradlePropertiesUserConfig.cdvMaxSdkVersion = maxSdkVersion;
if (targetSdkVersion) gradlePropertiesUserConfig.cdvTargetSdkVersion = targetSdkVersion;
// Both 'useAndroidX' and 'enableJetifier' are linked together.
if (androidXEnabled) {
gradlePropertiesUserConfig['android.useAndroidX'] = androidXEnabled;
gradlePropertiesUserConfig['android.enableJetifier'] = androidXEnabled;
}
let gradlePropertiesParser = new GradlePropertiesParser(this.locations.root);
gradlePropertiesParser.configure(gradlePropertiesUserConfig);

View File

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -18,4 +18,4 @@
include ':app'
include ":CordovaLib"
project(':CordovaLib').projectDir = new File('../framework')
project(':CordovaLib').projectDir = new File('../../framework')

60
test/androidx/README.md Normal file
View File

@ -0,0 +1,60 @@
<!--
#
# 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.
#
-->
# Cordova Android Test Project
The project in this directory is an Android Test project that enables those
interested in further developing `cordova-android` to validate their changes.
## Requirements
The requirements in the [top-level README](../README.md) still apply. In
addition, ensure you have installed Gradle, and that it is (at the time of this
writing) at least version 3.3 or newer.
## Getting Started
You can run this test project from both the command line as well as from
Android Studio:
### Command Line
Ensure you have the gradle wrapper script, `gradlew`, in this directory. If
you do not, you can run the following to generate it:
$ cd cordova-android/test
$ gradle :wrapper -b build.gradle
You can then see a list of all tasks available to run with `gradlew tasks`.
The two different kinds of tests one typically wants to run are unit tests and
end-to-end, or instrumented, tests. Unit tests do not require any particular
environment to run in, but the instrumented tests, however, require a connected
Android device or emulator to run in.
- To run the unit tests, run: `gradlew test`.
- To run the instrumented tests, run: `gradlew connectedAndroidTest`.
To make sure all tests are run, add the `--rerun-tasks` parameter.
### Android Studio
Import this `test/` directory into Android Studio, and hit the Play button.

1
test/androidx/app/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

View File

@ -0,0 +1,57 @@
/* 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.
*/
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
applicationId "org.apache.cordova.unittests"
minSdkVersion 19
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation project(path: ':CordovaLib')
implementation 'androidx.appcompat:appcompat:1.0.2'
testImplementation 'org.json:json:20140107'
testImplementation 'junit:junit:4.12'
androidTestImplementation('androidx.test.espresso:espresso-core:3.1.1', {
exclude group: 'androidx.test.espresso', module: 'androidx.annotation'
})
androidTestImplementation('androidx.test.espresso:espresso-web:3.1.1', {
exclude group: 'androidx.test.espresso', module: 'androidx.annotation'
})
}

36
test/androidx/app/proguard-rules.pro vendored Normal file
View File

@ -0,0 +1,36 @@
#
# 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.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /Users/jbowser/Library/Android/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

View File

@ -0,0 +1,158 @@
/*
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.unittests;
import android.content.Intent;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;
import org.apache.cordova.CordovaWebView;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.pressBack;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.web.sugar.Web.onWebView;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static org.apache.cordova.unittests.R.id.cordovaWebView;
@RunWith(AndroidJUnit4.class)
public class BackButtonMultipageTest {
private static final String START_URL = "file:///android_asset/www/backbuttonmultipage/index.html";
//I have no idea why we picked 100, but we did.
private static final int WEBVIEW_ID = 100;
private TestActivity mActivity;
// Don't launch the activity, we're going to send it intents
@Rule
public ActivityTestRule mActivityRule = new ActivityTestRule<>(
TestActivity.class, true, false);
@Before
public void launchApplicationWithIntent() {
Intent intent = new Intent();
intent.putExtra("startUrl", START_URL);
mActivity = (TestActivity) mActivityRule.launchActivity(intent);
}
@Test
public void testViaHref() throws Throwable {
final CordovaWebView webInterface = mActivity.getWebInterface();
assertEquals(START_URL, mActivity.onPageFinishedUrl.take());
mActivityRule.runOnUiThread(new Runnable() {
public void run() {
webInterface.sendJavascript("window.location = 'sample2.html';");
}
});
assertEquals("file:///android_asset/www/backbuttonmultipage/sample2.html", mActivity.onPageFinishedUrl.take());
mActivityRule.runOnUiThread(new Runnable() {
public void run() {
webInterface.sendJavascript("window.location = 'sample3.html';");
}
});
assertEquals("file:///android_asset/www/backbuttonmultipage/sample3.html", mActivity.onPageFinishedUrl.take());
mActivityRule.runOnUiThread(new Runnable() {
public void run() {
assertTrue(webInterface.backHistory());
}
});
assertEquals("file:///android_asset/www/backbuttonmultipage/sample2.html", mActivity.onPageFinishedUrl.take());
mActivityRule.runOnUiThread(new Runnable() {
public void run() {
assertTrue(webInterface.backHistory());
}
});
assertEquals(START_URL, mActivity.onPageFinishedUrl.take());
mActivityRule.runOnUiThread(new Runnable() {
public void run() {
assertFalse(webInterface.backHistory());
}
});
}
@Test
public void testViaLoadUrl() throws Throwable {
final CordovaWebView webInterface = mActivity.getWebInterface();
assertEquals(START_URL, mActivity.onPageFinishedUrl.take());
mActivityRule.runOnUiThread(new Runnable() {
public void run() {
webInterface.loadUrl("file:///android_asset/www/backbuttonmultipage/sample2.html");
}
});
assertEquals("file:///android_asset/www/backbuttonmultipage/sample2.html", mActivity.onPageFinishedUrl.take());
mActivityRule.runOnUiThread(new Runnable() {
public void run() {
webInterface.loadUrl("file:///android_asset/www/backbuttonmultipage/sample3.html");
}
});
assertEquals("file:///android_asset/www/backbuttonmultipage/sample3.html", mActivity.onPageFinishedUrl.take());
mActivityRule.runOnUiThread(new Runnable() {
public void run() {
assertTrue(webInterface.backHistory());
}
});
assertEquals("file:///android_asset/www/backbuttonmultipage/sample2.html", mActivity.onPageFinishedUrl.take());
mActivityRule.runOnUiThread(new Runnable() {
public void run() {
assertTrue(webInterface.backHistory());
}
});
assertEquals(START_URL, mActivity.onPageFinishedUrl.take());
mActivityRule.runOnUiThread(new Runnable() {
public void run() {
assertFalse(webInterface.backHistory());
}
});
}
@Test
public void testViaBackButtonOnView() throws Throwable {
final CordovaWebView webInterface = mActivity.getWebInterface();
assertEquals(START_URL, mActivity.onPageFinishedUrl.take());
mActivityRule.runOnUiThread(new Runnable() {
public void run() {
webInterface.loadUrl("file:///android_asset/www/backbuttonmultipage/sample2.html");
}
});
assertEquals("file:///android_asset/www/backbuttonmultipage/sample2.html", mActivity.onPageFinishedUrl.take());
mActivityRule.runOnUiThread(new Runnable() {
public void run() {
webInterface.loadUrl("file:///android_asset/www/backbuttonmultipage/sample3.html");
}
});
assertEquals("file:///android_asset/www/backbuttonmultipage/sample3.html", mActivity.onPageFinishedUrl.take());
onView(withId(WEBVIEW_ID)).perform(pressBack());
assertEquals("file:///android_asset/www/backbuttonmultipage/sample2.html", mActivity.onPageFinishedUrl.take());
onView(withId(WEBVIEW_ID)).perform(pressBack());
assertEquals(START_URL, mActivity.onPageFinishedUrl.take());
}
}

View File

@ -0,0 +1,53 @@
/*
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.unittests;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import static junit.framework.Assert.assertNotNull;
/*
* This test is to cover the use case of Cordova Android used as a component in a larger Android
* application. This test is strictly used to cover this use case. In this example, the WebView
* should load, not be null, and the Plugin Manager should also be initialized.
*
*/
@RunWith(AndroidJUnit4.class)
public class EmbeddedWebViewTest {
@Rule
public ActivityTestRule mActivityRule = new ActivityTestRule<>(
EmbeddedWebViewActivity.class);
@Test
public void checkWebViewTest() {
EmbeddedWebViewActivity activity = (EmbeddedWebViewActivity) mActivityRule.getActivity();
assertNotNull(activity.webInterface);
assertNotNull(activity.webInterface.getPluginManager());
}
}

View File

@ -0,0 +1,68 @@
/*
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.unittests;
import android.content.Intent;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;
import org.apache.cordova.CordovaWebView;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import static junit.framework.Assert.assertEquals;
@RunWith(AndroidJUnit4.class)
public class ErrorUrlTest {
private static final String START_URL = "file:///android_asset/www/htmlnotfound/index.html";
private static final String ERROR_URL = "file:///android_asset/www/htmlnotfound/error.html";
private static final String INVALID_URL = "file:///android_asset/www/invalid.html";
//I have no idea why we picked 100, but we did.
private static final int WEBVIEW_ID = 100;
private TestActivity mActivity;
@Rule
public ActivityTestRule mActivityRule = new ActivityTestRule<>(
TestActivity.class);
@Before
public void launchApplicationWithIntent() {
Intent intent = new Intent();
intent.putExtra("startUrl", START_URL);
intent.putExtra("errorurl", INVALID_URL);
intent.putExtra("url", INVALID_URL);
mActivity = (TestActivity) mActivityRule.launchActivity(intent);
}
@Test
public void errorUrlTest() throws Throwable {
assertEquals(START_URL, mActivity.onPageFinishedUrl.take());
assertEquals(ERROR_URL, mActivity.onPageFinishedUrl.take());
mActivityRule.runOnUiThread(new Runnable() {
public void run() {
assertEquals(ERROR_URL, mActivity.getWebInterface().getUrl());
}
});
}
}

View File

@ -0,0 +1,114 @@
/*
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.unittests;
import android.content.Intent;
import androidx.test.espresso.web.webdriver.Locator;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;
import org.apache.cordova.CordovaWebView;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.action.ViewActions.pressBack;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.web.sugar.Web.onWebView;
import static androidx.test.espresso.web.webdriver.DriverAtoms.findElement;
import static androidx.test.espresso.web.webdriver.DriverAtoms.webClick;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
@RunWith(AndroidJUnit4.class)
public class IFrameTest {
private static final String START_URL = "file:///android_asset/www/iframe/index.html";
//I have no idea why we picked 100, but we did.
private static final int WEBVIEW_ID = 100;
private int WEBVIEW_LOAD_DELAY = 500;
private TestActivity testActivity;
// Don't launch the activity, we're going to send it intents
@Rule
public ActivityTestRule mActivityRule = new ActivityTestRule<>(
TestActivity.class, true, false);
@Before
public void launchApplicationWithIntent() {
Intent intent = new Intent();
intent.putExtra("startUrl", START_URL);
testActivity = (TestActivity) mActivityRule.launchActivity(intent);
}
@Test
public void iFrameHistory() throws Throwable {
final CordovaWebView cordovaWebView = (CordovaWebView) testActivity.getWebInterface();
onWebView().withElement(findElement(Locator.ID, "google_maps")).perform(webClick());
sleep(WEBVIEW_LOAD_DELAY);
mActivityRule.runOnUiThread(new Runnable() {
public void run()
{
String url = cordovaWebView.getUrl();
assertTrue(url.endsWith("index.html"));
}
});
sleep(WEBVIEW_LOAD_DELAY);
onWebView().withElement(findElement(Locator.ID, "javascript_load")).perform(webClick());
mActivityRule.runOnUiThread(new Runnable() {
public void run()
{
String url = cordovaWebView.getUrl();
assertTrue(url.endsWith("index.html"));
}
});
sleep(WEBVIEW_LOAD_DELAY);
//Espresso will kill the application and not trigger the backHistory method, which correctly
//navigates the iFrame history. backHistory is tied to the back button.
mActivityRule.runOnUiThread(new Runnable() {
public void run()
{
assertTrue(cordovaWebView.backHistory());
String url = cordovaWebView.getUrl();
assertTrue(url.endsWith("index.html"));
assertFalse(cordovaWebView.backHistory());
}
});
}
//BRUTE FORCE THE CRAP OUT OF CONCURRENCY ERRORS
private void sleep(int timeout) {
try {
Thread.sleep(timeout);
} catch (InterruptedException e) {
fail("Unexpected Timeout");
}
}
}

View File

@ -0,0 +1,130 @@
/*
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.unittests;
import android.content.Intent;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CordovaWebViewImpl;
import org.apache.cordova.PluginManager;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.fail;
@RunWith(AndroidJUnit4.class)
public class MessageChannelMultipageTest {
private static final String START_URL = "file:///android_asset/www/backbuttonmultipage/index.html";
//I have no idea why we picked 100, but we did.
private static final int WEBVIEW_ID = 100;
private TestActivity testActivity;
@Rule
public ActivityTestRule mActivityRule = new ActivityTestRule<>(
TestActivity.class);
@Before
public void launchApplicationWithIntent() {
Intent intent = new Intent();
intent.putExtra("startUrl", START_URL);
testActivity = (TestActivity) mActivityRule.launchActivity(intent);
}
//test that after a page load the cached callback id and the live callback id match
//this is to prevent a regression
//the issue was that CordovaWebViewImpl's cached instance of CoreAndroid would become stale on page load
//this is because the cached instance was not being cleared when the pluginManager was reset on page load
//the plugin manager would get a new instance which would be updated with a new callback id
//the cached instance's message channel callback id would become stale
//effectively this caused message channel events to not be delivered
@Test
public void testThatCachedCallbackIdIsValid() throws Throwable {
final CordovaWebView cordovaWebView = testActivity.getWebInterface();
Class cordovaWebViewImpl = CordovaWebViewImpl.class;
//send a test event - this initializes cordovaWebViewImpl.appPlugin (the cached instance of CoreAndroid)
Method method = cordovaWebViewImpl.getDeclaredMethod("sendJavascriptEvent", String.class);
method.setAccessible(true);
method.invoke(cordovaWebView, "testEvent");
sleep(1000);
//load a page - this resets the plugin manager and nulls cordovaWebViewImpl.appPlugin
//(previously this resets plugin manager but did not null cordovaWebViewImpl.appPlugin, leading to the issue)
mActivityRule.runOnUiThread(new Runnable() {
public void run() {
cordovaWebView.loadUrl(START_URL);
}
});
assertEquals(START_URL, testActivity.onPageFinishedUrl.take());
//send a test event - this initializes cordovaWebViewImpl.appPlugin (the cached instance of CoreAndroid)
method.invoke(cordovaWebView, "testEvent");
sleep(1000);
//get reference to package protected class CoreAndroid
Class coreAndroid = Class.forName("org.apache.cordova.CoreAndroid");
//get cached CoreAndroid
Field appPluginField = cordovaWebViewImpl.getDeclaredField("appPlugin");
appPluginField.setAccessible(true);
Object cachedAppPlugin = appPluginField.get(cordovaWebView);
//get cached CallbackContext
Field messageChannelField = coreAndroid.getDeclaredField("messageChannel");
messageChannelField.setAccessible(true);
CallbackContext cachedCallbackContext = (CallbackContext) messageChannelField.get(cachedAppPlugin);
//get live CoreAndroid
PluginManager pluginManager = cordovaWebView.getPluginManager();
Field coreAndroidPluginNameField = coreAndroid.getField("PLUGIN_NAME");
String coreAndroidPluginName = (String) coreAndroidPluginNameField.get(null);
Object liveAppPlugin = pluginManager.getPlugin(coreAndroidPluginName);
//get live CallbackContext
CallbackContext liveCallbackContext = (CallbackContext) messageChannelField.get(liveAppPlugin);
//get callback id from live callbackcontext
String liveCallbackId = (liveCallbackContext != null) ? liveCallbackContext.getCallbackId() : null;
//get callback id from cached callbackcontext
String cachedCallbackId = (cachedCallbackContext != null) ? cachedCallbackContext.getCallbackId() : null;
//verify that the live message channel has been initialized
assertNotNull(liveCallbackId);
//verify that the cached message channel and the live message channel have the same id
assertEquals(liveCallbackId, cachedCallbackId);
}
private void sleep(int timeout) {
try {
Thread.sleep(timeout);
} catch (InterruptedException e) {
fail("Unexpected Timeout");
}
}
}

View File

@ -0,0 +1,100 @@
/*
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.unittests;
import android.content.Intent;
import android.graphics.Color;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;
import android.view.View;
import android.widget.LinearLayout;
import org.apache.cordova.CordovaPreferences;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.engine.SystemWebView;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNotSame;
import static junit.framework.Assert.assertTrue;
/**
* The purpose of this test is to test the default application that is generated by Cordova itself
*
*/
@RunWith(AndroidJUnit4.class)
public class StandardActivityTest {
private static final String FALSE_URI = "http://www.google.com";
// Don't launch the activity, we're going to send it intents
@Rule
public ActivityTestRule mActivityRule = new ActivityTestRule<>(
StandardActivity.class, true, false);
@Before
public void launchApplicationWithIntent() {
Intent intent = new Intent();
intent.putExtra("startUrl", FALSE_URI);
intent.putExtra("backgroundcolor", "#0000ff");
mActivityRule.launchActivity(intent);
}
@Test
public void webViewCheck() {
StandardActivity activity = (StandardActivity) mActivityRule.getActivity();
//Fish the webview out of the mostly locked down Activity using the Android SDK
View view = activity.getWindow().getCurrentFocus();
assertEquals(SystemWebView.class, view.getClass());
}
@Test
public void startUriIntentCheck() {
StandardActivity activity = (StandardActivity) mActivityRule.getActivity();
final SystemWebView webView = (SystemWebView) activity.getWindow().getCurrentFocus();
try {
mActivityRule.runOnUiThread(new Runnable() {
@Override
public void run() {
String uri = webView.getUrl();
assertFalse(uri.equals(FALSE_URI));
}
});
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
@Test
public void checkBackgroundIntentCheck() {
StandardActivity activity = (StandardActivity) mActivityRule.getActivity();
final SystemWebView webView = (SystemWebView) activity.getWindow().getCurrentFocus();
CordovaWebView webInterface = webView.getCordovaWebView();
CordovaPreferences prefs = webInterface.getPreferences();
assertFalse(prefs.getInteger("backgroundcolor", Color.BLACK) == Color.GREEN);
}
}

View File

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.apache.cordova.unittests">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".EmbeddedWebViewActivity"
android:configChanges="orientation|keyboardHidden"
android:label="@string/app_name"
android:windowSoftInputMode="adjustPan">
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".StandardActivity"
android:configChanges="orientation|keyboardHidden"
android:label="@string/app_name"
android:windowSoftInputMode="adjustPan">
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".TestActivity"
android:configChanges="orientation|keyboardHidden"
android:label="@string/app_name"
android:windowSoftInputMode="adjustPan">
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@ -0,0 +1,40 @@
<!--
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.
-->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Backbutton</title>
<link rel="stylesheet" href="../master.css" type="text/css" media="screen" title="no title">
<script type="text/javascript" charset="utf-8" src="../cordova.js"></script>
<script type="text/javascript" charset="utf-8" src="../main.js"></script>
<body onload="init();" id="stage" class="theme">
<h1>Cordova Android Tests</h1>
<div id="info">
<h4>Cordova: <span id="cordova"> &nbsp;</span></h4>
<h4>Deviceready: <span id="deviceready"> &nbsp;</span></h4>
</div>
<div id="info">
<h4>Page 1</h4>
Go to next page.<br>
If returning from previous page, press "backbutton". You should exit this app.
</div>
<a href="sample2.html" class="btn large">Next page</a>
</body>
</html>

View File

@ -0,0 +1,40 @@
<!--
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.
-->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Backbutton</title>
<link rel="stylesheet" href="../master.css" type="text/css" media="screen" title="no title">
<script type="text/javascript" charset="utf-8" src="../cordova.js"></script>
<script type="text/javascript" charset="utf-8" src="../main.js"></script>
<body onload="init();" id="stage" class="theme">
<h1>Cordova Android Tests</h1>
<div id="info">
<h4>Cordova: <span id="cordova"> &nbsp;</span></h4>
<h4>Deviceready: <span id="deviceready"> &nbsp;</span></h4>
</div>
<div id="info">
<h4>Page 2</h4>
Go to next page.<br>
If returning from previous page, press "backbutton". You should go to Page 1.
</div>
<a href="sample3.html" class="btn large">Next page</a>
</body>
</html>

View File

@ -0,0 +1,42 @@
<!--
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.
-->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Backbutton</title>
<link rel="stylesheet" href="../master.css" type="text/css" media="screen" title="no title">
<script type="text/javascript" charset="utf-8" src="../cordova.js"></script>
<script type="text/javascript" charset="utf-8" src="../main.js"></script>
<body onload="init();" id="stage" class="theme">
<h1>Cordova Android Tests</h1>
<div id="info">
<h4>Cordova: <span id="cordova"> &nbsp;</span></h4>
<h4>Deviceready: <span id="deviceready"> &nbsp;</span></h4>
</div>
<div id="info">
<h4>Page 3</h4>
Press the 3 buttons below. You should stay on same page.<br>
Press "backbutton" 4 times. This will go back to #test3, #test2, #test1, then return to previous Page 2.<br>
</div>
<a href="sample3.html#test1" class="btn large">page3#test1</a>
<a href="sample3.html#test2" class="btn large">page3#test2</a>
<a href="sample3.html#test3" class="btn large">page3#test3</a>
</body>
</html>

View File

@ -0,0 +1,39 @@
<!--
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.
-->
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=320, user-scalable=no" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Cordova Tests</title>
<link rel="stylesheet" href="../master.css" type="text/css" media="screen" title="no title">
<script type="text/javascript" charset="utf-8" src="../cordova.js"></script>
<script type="text/javascript" charset="utf-8" src="../main.js"></script>
</head>
<body onload="init();" id="stage" class="theme">
<h1>Background Color Test</h1>
<div id="info">
<h4>Cordova: <span id="cordova"> &nbsp;</span></h4>
<h4>Deviceready: <span id="deviceready"> &nbsp;</span></h4>
</div>
<div id="info">
Before this page was show, you should have seen the background flash green.</br>
</div>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,22 @@
/*
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.
*/
cordova.define('cordova/plugin_list', function(require, exports, module) {
module.exports = [];
});

View File

@ -0,0 +1,40 @@
<!--
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.
-->
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=320, user-scalable=no" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Cordova Tests</title>
<link rel="stylesheet" href="../master.css" type="text/css" media="screen" title="no title">
<script type="text/javascript" charset="utf-8" src="../cordova.js"></script>
<script type="text/javascript" charset="utf-8" src="../main.js"></script>
</head>
<body onload="init();" id="stage" class="theme">
<h1>Full Screen Test</h1>
<div id="info">
<h4>Cordova: <span id="cordova"> &nbsp;</span></h4>
<h4>Deviceready: <span id="deviceready"> &nbsp;</span></h4>
</div>
<div id="info">
The app should take over the entire screen. <br>
The top Android status bar should not be shown.
</div>
</body>
</html>

View File

@ -0,0 +1,38 @@
<!--
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.
-->
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=320, user-scalable=no" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Expected Error</title>
<link rel="stylesheet" href="../master.css" type="text/css" media="screen" title="no title">
<script type="text/javascript" charset="utf-8" src="../cordova.js"></script>
<script type="text/javascript" charset="utf-8" src="../main.js"></script>
</head>
<body onload="init();" id="stage" class="theme">
<h1>Expected Error</h1>
<div id="info">
<h4>Cordova: <span id="cordova"> &nbsp;</span></h4>
<h4>Deviceready: <span id="deviceready"> &nbsp;</span></h4>
</div>
<div id="info">
This is an expected error page because the initial href doesn't exist.
</body>
</html>

View File

@ -0,0 +1,49 @@
<!DOCTYPE HTML>
<!--
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.
-->
<html>
<head>
<meta name="viewport" content="width=320, user-scalable=no" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Cordova Tests</title>
<link rel="stylesheet" href="../master.css" type="text/css" media="screen" title="no title">
<script type="text/javascript" charset="utf-8" src="../cordova.js"></script>
<script type="text/javascript" charset="utf-8" src="../main.js"></script>
<script>
function loadUrl(url) {
document.getElementById('iframe').src = url;
}</script>
</head>
<body onload="init();" id="stage" class="theme">
<h1>IFrame</h1>
<div id="info">
<h4>Cordova: <span id="cordova"> &nbsp;</span></h4>
<h4>Deviceready: <span id="deviceready"> &nbsp;</span></h4>
</div>
<div id="info">
Press the two buttons:<br>
1. Google Maps should display in iframe.<br>
2. Page 2 replaces current page.<br>
(NOTE: THIS BEHAVIOR IS WRONG - AND NEEDS TO BE FIXED IN FUTURE RELEASE.)
</div>
<iframe id="iframe" src="" width="90%" height="200px"></iframe>
<a id="google_maps" href="javascript:" class="btn large" onclick="loadUrl('http://maps.google.com/maps?output=embed');">Google Maps</a>
<a id="javascript_load" href="javascript:" class="btn large" onclick="loadUrl('index2.html');">Page 2</a>
</body>
</html>

View File

@ -0,0 +1,40 @@
<!DOCTYPE HTML>
<!--
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.
-->
<html>
<head>
<meta name="viewport" content="width=320, user-scalable=no" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Cordova Tests</title>
<link rel="stylesheet" href="../master.css" type="text/css" media="screen" title="no title">
<script type="text/javascript" charset="utf-8" src="../cordova.js"></script>
<script type="text/javascript" charset="utf-8" src="../main.js"></script>
</head>
<body onload="init();" id="stage" class="theme">
<h1>IFrame window</h1>
<div id="info">
<h4>Cordova: <span id="cordova"> &nbsp;</span></h4>
<h4>Deviceready: <span id="deviceready"> &nbsp;</span></h4>
</div>
<div id="info">
This should display a Cordova page inside an iframe. The info above should be filled out.
(NOTE: THIS DOES NOT WORK AND NEEDS TO BE FIXED IN FUTURE RELEASE.)
</div>
</body>
</html>

View File

@ -0,0 +1,56 @@
<!--
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.
-->
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=320, user-scalable=no" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Cordova Tests</title>
<link rel="stylesheet" href="master.css" type="text/css" media="screen" title="no title">
<script type="text/javascript" charset="utf-8" src="cordova.js"></script>
<script type="text/javascript" charset="utf-8" src="main.js"></script>
<script>
function startActivity(url, opts, className) {
cordova.exec(function() {console.log("Success");}, function(e) {console.log("Error: "+e);}, "Activity", "start", [className, url, opts || {}]);
};
localStorage.lifecyclestatus = "";
localStorage.backgroundstatus = "";
</script>
</head>
<body onload="init();" id="stage" class="theme">
<h1>Cordova Android Native Tests</h1>
<div id="info">
<h4>Cordova: <span id="cordova"> &nbsp;</span></h4>
<h4>Deviceready: <span id="deviceready"> &nbsp;</span></h4>
</div>
<div id="info">
<h4>Run each of the test activities below:</h4>
</div>
<button class="btn large" onclick="startActivity('backbuttonmultipage/index.html');">Backbutton with multiple pages</button>
<button class="btn large" onclick="startActivity('backgroundcolor/index.html', {backgroundcolor: -16711936});">Background Color</button>
<button class="btn large" onclick="startActivity('errorurl/index.html', {testErrorUrl: 'file:///android_asset/www/htmlnotfound/error.html'});">Error URL</button>
<button class="btn large" onclick="startActivity('fullscreen/index.html', {fullscreen: true});">Full Screen</button>
<button class="btn large" onclick="startActivity('htmlnotfound/index.html');">HTML not found</button>
<button class="btn large" onclick="startActivity('iframe/index.html');">IFrame</button>
<button class="btn large" onclick="startActivity('lifecycle/index.html');">Lifecycle</button>
<button class="btn large" onclick="startActivity('whitelist/index.html');">Whitelist</button>
</body>
</html>

View File

@ -0,0 +1,112 @@
<!DOCTYPE HTML>
<!--
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.
-->
<html>
<head>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Lifecycle Page 1</title>
<link rel="stylesheet" href="../master.css" type="text/css" media="screen" title="no title">
<script type="text/javascript" charset="utf-8" src="../cordova.js"></script>
<script type="text/javascript" charset="utf-8">
function onLoad() {
console.log("Page1: onload");
log("Page1: onload @ " + new Date().toLocaleTimeString());
document.addEventListener("deviceready", onDeviceReady, false);
}
function onUnLoaded() {
console.log("Page1: onunload");
log("Page1: onunload @ " + new Date().toLocaleTimeString());
}
function onDeviceReady() {
// Register the event listener
document.getElementById("deviceready").innerHTML = "fired";
document.getElementById("cordova").innerHTML = cordova.version;
document.addEventListener("pause", onPause, false);
document.addEventListener("resume", onResume, false);
window.setInterval(function() {
log("Page1: Running");
}, 2000);
}
function onPause() {
console.log("Page1: onpause");
log("Page1: onpause @ " + new Date().toLocaleTimeString());
}
function onResume() {
console.log("Page1: onresume");
log("Page1: onresume @ " + new Date().toLocaleTimeString());
}
function log(s) {
var el = document.getElementById('status');
var status = el.innerHTML + s + "<br>";
el.innerHTML = status;
localStorage.lifecyclestatus = status;
}
function clearStatus() {
console.log("clear()");
localStorage.lifecyclestatus = "";
document.getElementById('status').innerHTML = "";
}
</script>
</head>
<body onload="onLoad()" onunload="onUnLoaded()" id="stage" class="theme">
<h1>Events</h1>
<div id="info">
<h4>Cordova: <span id="cordova"> &nbsp;</span></h4>
<h4>Deviceready: <span id="deviceready"> &nbsp;</span></h4>
</div>
<div id="info">
<h4>Test 1</h4>
Press "Home" button, then return to this app to see pause/resume.<br>
There should be "Running" entries between pause and resume since app continues to run in the background.
<h4>Test 2</h4>
Press "Load new page" button to load a new Cordova page.<br>
When returning, you should see
<ul>
<li>Page2: onunload</li>
<li>Page1: onload</li>
<li>Page1: Running</li>
</ul>
</div>
<div id="info">
<h4>Info for event testing:</h4>
<div id="status"></div>
</div>
<a href="index2.html" class="btn large" >Load new page</a>
<a href="javascript:" class="btn large" onclick="clearStatus();">Clear status</a>
<script>
document.getElementById('status').innerHTML = localStorage.lifecyclestatus;
</script>
</body>
</html>

View File

@ -0,0 +1,110 @@
<!--
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.
-->
<!DOCTYPE HTML>
<html>
<head>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Lifecycle Page 2</title>
<link rel="stylesheet" href="../master.css" type="text/css" media="screen" title="no title">
<script type="text/javascript" charset="utf-8" src="../cordova.js"></script>
<script type="text/javascript" charset="utf-8">
function onLoad() {
console.log("Page2: onload");
log("Page2: onload @ " + new Date().toLocaleTimeString());
document.addEventListener("deviceready", onDeviceReady, false);
}
function onUnLoaded() {
console.log("Page2: onunload");
log("Page2: onunload @ " + new Date().toLocaleTimeString());
}
function onDeviceReady() {
// Register the event listener
document.getElementById("deviceready").innerHTML = "fired";
document.getElementById("cordova").innerHTML = cordova.version;
document.addEventListener("pause", onPause, false);
document.addEventListener("resume", onResume, false);
window.setInterval(function() {
log("Page2: Running");
}, 2000);
}
function onPause() {
console.log("Page2: onpause");
log("Page2: onpause @ " + new Date().toLocaleTimeString());
}
function onResume() {
console.log("Page2: onresume");
log("Page2: onresume @ " + new Date().toLocaleTimeString());
}
function log(s) {
var el = document.getElementById('status');
var status = el.innerHTML + s + "<br>";
el.innerHTML = status;
localStorage.lifecyclestatus = status;
}
function clearStatus() {
console.log("clear()");
localStorage.lifecyclestatus = "";
document.getElementById('status').innerHTML = "";
}
</script>
</head>
<body onload="onLoad()" onunload="onUnLoaded()" id="stage" class="theme">
<h1>Events</h1>
<div id="info">
<h4>Cordova: <span id="cordova"> &nbsp;</span></h4>
<h4>Platform: <span id="platform"> &nbsp;</span>, Version: <span id="version">&nbsp;</span></h4>
<h4>UUID: <span id="uuid"> &nbsp;</span>, Name: <span id="name">&nbsp;</span></h4>
<h4>Width: <span id="width"> &nbsp;</span>, Height: <span id="height">&nbsp;</span>, Color Depth: <span id="colorDepth"></span></h4>
</div>
<div id="info">
You should see<br>
<ul>
<li>Page1: onunload</li>
<li>Page2: onload</li>
<li>Page2: Running</li>
</ul>
Press "backbutton" to return to Page 1.
</div>
<div id="info">
<h4>Info for event testing:</h4>
<div id="status"></div>
</div>
<a href="index.html" class="btn large" >Load new page</a>
<a href="javascript:" class="btn large" onclick="clearStatus();">Clear status</a>
<script>
document.getElementById('status').innerHTML = localStorage.lifecyclestatus;
</script>
</body>
</html>

View File

@ -0,0 +1,27 @@
/*
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.
*/
var deviceInfo = function() {
document.getElementById("deviceready").innerHTML = "fired";
document.getElementById("cordova").innerHTML = cordova.version;
};
function init() {
document.addEventListener("deviceready", deviceInfo, true);
}

View File

@ -0,0 +1,136 @@
/*
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.
*/
body {
background:#222 none repeat scroll 0 0;
color:#666;
font-family:Helvetica;
font-size:72%;
line-height:1.5em;
margin:0;
border-top:1px solid #393939;
}
#info{
background:#ffa;
border: 1px solid #ffd324;
-webkit-border-radius: 5px;
border-radius: 5px;
clear:both;
margin:15px 6px 0;
width:295px;
padding:4px 0px 2px 10px;
}
#info > h4{
font-size:.95em;
margin:5px 0;
}
#stage.theme{
padding-top:3px;
}
/* Definition List */
#stage.theme > dl{
padding-top:10px;
clear:both;
margin:0;
list-style-type:none;
padding-left:10px;
overflow:auto;
}
#stage.theme > dl > dt{
font-weight:bold;
float:left;
margin-left:5px;
}
#stage.theme > dl > dd{
width:45px;
float:left;
color:#a87;
font-weight:bold;
}
/* Content Styling */
#stage.theme > h1, #stage.theme > h2, #stage.theme > p{
margin:1em 0 .5em 13px;
}
#stage.theme > h1{
color:#eee;
font-size:1.6em;
text-align:center;
margin:0;
margin-top:15px;
padding:0;
}
#stage.theme > h2{
clear:both;
margin:0;
padding:3px;
font-size:1em;
text-align:center;
}
/* Stage Buttons */
#stage.theme a.btn{
border: 1px solid #555;
-webkit-border-radius: 5px;
border-radius: 5px;
text-align:center;
display:block;
float:left;
background:#444;
width:150px;
color:#9ab;
font-size:1.1em;
text-decoration:none;
padding:1.2em 0;
margin:3px 0px 3px 5px;
}
#stage.theme a.btn.large{
width:308px;
padding:1.2em 0;
}
/* Stage Buttons */
#stage.theme button.btn{
border: 1px solid #555;
-webkit-border-radius: 5px;
border-radius: 5px;
text-align:center;
display:block;
float:left;
background:#444;
width:150px;
color:#9ab;
font-size:1.1em;
text-decoration:none;
padding:1.2em 0;
margin:3px 0px 3px 5px;
}
#stage.theme button.btn.large{
width:308px;
padding:1.2em 0;
}

View File

@ -0,0 +1,45 @@
<!--
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.
-->
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=320, user-scalable=no" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Cordova Tests</title>
<link rel="stylesheet" href="../master.css" type="text/css" media="screen" title="no title">
<script type="text/javascript" charset="utf-8" src="../cordova.js"></script>
<script type="text/javascript" charset="utf-8" src="../main.js"></script>
</head>
<body onload="init();" id="stage" class="theme">
<h1>Whitelist Page 1</h1>
<div id="info">
<h4>Cordova: <span id="cordova"> &nbsp;</span></h4>
<h4>Deviceready: <span id="deviceready"> &nbsp;</span></h4>
</div>
<div id="info">
Loading Page 2 should be successful.<br>
Loading Page 3 should be in web browser.<br>
Loading Page 2 with target=_blank should be in web browser? <br>
(THIS DOESN'T HAPPEN.) https://issues.apache.org/jira/browse/CB-362
</div>
<a href="index2.html" class="btn large">Page 2</a>
<a href="http://www.google.com" class="btn large">Page 3</a>
<a href="index2.html" class="btn large" target="_blank">Page 2 with target=_blank</a>
</body>
</html>

View File

@ -0,0 +1,39 @@
<!--
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.
-->
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=320, user-scalable=no" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Cordova Tests</title>
<link rel="stylesheet" href="../master.css" type="text/css" media="screen" title="no title">
<script type="text/javascript" charset="utf-8" src="../cordova.js"></script>
<script type="text/javascript" charset="utf-8" src="../main.js"></script>
</head>
<body onload="init();" id="stage" class="theme">
<h1>Whitelist Page 2</h1>
<div id="info">
<h4>Cordova: <span id="cordova"> &nbsp;</span></h4>
<h4>Deviceready: <span id="deviceready"> &nbsp;</span></h4>
</div>
<div id="info">
Press "backbutton"
</div>
</body>
</html>

View File

@ -0,0 +1,110 @@
/*
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.unittests;
import android.content.Intent;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import org.apache.cordova.ConfigXmlParser;
import org.apache.cordova.CordovaInterfaceImpl;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CordovaWebViewImpl;
import org.apache.cordova.PluginManager;
import org.apache.cordova.engine.SystemWebView;
import org.apache.cordova.engine.SystemWebViewEngine;
import org.json.JSONException;
public class EmbeddedWebViewActivity extends AppCompatActivity {
public CordovaWebView webInterface;
private CordovaInterfaceImpl cordovaInterface = new CordovaInterfaceImpl(this);
private String TAG = "CordovaTestActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Set up the webview
ConfigXmlParser parser = new ConfigXmlParser();
parser.parse(this);
SystemWebView webView = (SystemWebView) findViewById(R.id.cordovaWebView);
webInterface = new CordovaWebViewImpl(new SystemWebViewEngine(webView));
webInterface.init(cordovaInterface, parser.getPluginEntries(), parser.getPreferences());
webView.loadUrl(parser.getLaunchUrl());
}
// This is still required by Cordova
@Override
public void onDestroy()
{
super.onDestroy();
PluginManager pluginManager = webInterface.getPluginManager();
if(pluginManager != null)
{
pluginManager.onDestroy();
}
}
/**
* Called when an activity you launched exits, giving you the requestCode you started it with,
* the resultCode it returned, and any additional data from it.
*
* @param requestCode The request code originally supplied to startActivityForResult(),
* allowing you to identify who this result came from.
* @param resultCode The integer result code returned by the child activity through its setResult().
* @param intent An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
cordovaInterface.onActivityResult(requestCode, resultCode, intent);
}
/**
* Called by the system when the user grants permissions!
*
* Note: The fragment gets priority over the activity, since the activity doesn't call
* into the parent onRequestPermissionResult, which is why there's no override.
*
* @param requestCode
* @param permissions
* @param grantResults
*/
public void onRequestPermissionsResult(int requestCode, String permissions[],
int[] grantResults) {
try
{
cordovaInterface.onRequestPermissionResult(requestCode, permissions, grantResults);
}
catch (JSONException e)
{
Log.d(TAG, "JSONException: Parameters fed into the method are not valid");
e.printStackTrace();
}
}
}

View File

@ -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.unittests;
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");
}
}

View File

@ -0,0 +1,42 @@
/*
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.unittests;
import android.os.Bundle;
import org.apache.cordova.CordovaActivity;
public class StandardActivity extends CordovaActivity {
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// enable Cordova apps to be started in the background
Bundle extras = getIntent().getExtras();
if (extras != null && extras.getBoolean("cdvStartInBackground", false)) {
moveTaskToBack(true);
}
// Set by <content src="index.html" /> in config.xml
loadUrl(launchUrl);
}
}

View File

@ -0,0 +1,67 @@
/*
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.unittests;
import android.os.Bundle;
import org.apache.cordova.CordovaActivity;
import org.apache.cordova.CordovaWebView;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.RunnableFuture;
/**
* The purpose of this activity is to allow the test framework to manipulate the start url, which
* is normally locked down by CordovaActivity to standard users who aren't editing their Java code.
*/
public class TestActivity extends CordovaActivity {
public final ArrayBlockingQueue<String> onPageFinishedUrl = new ArrayBlockingQueue<String>(500);
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// enable Cordova apps to be started in the background
Bundle extras = getIntent().getExtras();
if (extras != null) {
if (extras.getBoolean("cdvStartInBackground", false)) {
moveTaskToBack(true);
}
launchUrl = extras.getString("startUrl", "index.html");
}
// Set by <content src="index.html" /> in config.xml
loadUrl(launchUrl);
}
@Override
public Object onMessage(String id, Object data) {
if ("onPageFinished".equals(id)) {
onPageFinishedUrl.add((String) data);
}
return super.onMessage(id, data);
}
public CordovaWebView getWebInterface() { return this.appView; }
}

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="org.apache.cordova.unittests.EmbeddedWebViewActivity">
<org.apache.cordova.engine.SystemWebView
android:id="@+id/cordovaWebView"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</RelativeLayout>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -0,0 +1,24 @@
<resources>
<!--
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.
-->
<!-- Example customization of dimensions originally defined in res/values/dimens.xml
(such as screen margins) for screens with more than 820dp of available width. This
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
<dimen name="activity_horizontal_margin">64dp</dimen>
</resources>

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<resources>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
</resources>

View File

@ -0,0 +1,23 @@
<resources>
<!--
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.
-->
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
</resources>

View File

@ -0,0 +1,22 @@
<resources>
<!--
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.
-->
<string name="app_name">UnitTests</string>
</resources>

View File

@ -0,0 +1,29 @@
<resources>
<!--
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.
-->
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
</resources>

View File

@ -0,0 +1,44 @@
<?xml version='1.0' encoding='utf-8'?>
<!--
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.
-->
<widget id="io.cordova.helloCordova" version="2.0.0" xmlns="http://www.w3.org/ns/widgets">
<name>Hello Cordova</name>
<description>
A sample Apache Cordova application that responds to the deviceready event.
</description>
<author email="dev@cordova.apache.org" href="http://cordova.io">
Apache Cordova Team
</author>
<access origin="*.apache.org" />
<access origin="http://*.google.com/*" />
<access origin="https://*.google.com/*" />
<access origin="https://*.googleapis.com/*" />
<access origin="https://*.gstatic.com/*" />
<content src="index.html" />
<preference name="errorUrl" value="file:///android_asset/www/htmlnotfound/error.html" />
<preference name="loglevel" value="DEBUG" />
<preference name="useBrowserHistory" value="true" />
<preference name="exit-on-suspend" value="false" />
<preference name="showTitle" value="true" />
<preference name="BackgroundColor" value="#000000" />
<feature name="LifeCycle">
<param name="android-package" value="org.apache.cordova.unittests.LifeCyclePlugin" />
<param name="onload" value="true" />
</feature>
</widget>

View File

@ -0,0 +1,177 @@
/*
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.unittests;
import android.app.Activity;
import android.content.Intent;
import android.view.View;
import android.webkit.ValueCallback;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaResourceApi;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CordovaWebViewEngine;
import org.apache.cordova.ICordovaCookieManager;
import org.apache.cordova.NativeToJsMessageQueue;
import org.apache.cordova.PluginManager;
import org.apache.cordova.PluginResult;
import org.apache.cordova.engine.SystemWebViewEngine;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import static org.junit.Assert.*;
public class NativeToJsMessageQueueTest {
NativeToJsMessageQueue queue = new NativeToJsMessageQueue();
private String TEST_CALLBACK_ID = "MessageQueueTest";
//A queue with no bridges should not work
@Test
public void testEmptyBridge()
{
assertFalse(queue.isBridgeEnabled());
}
//A queue with at least one bridge should work, using Eval Bridge
@Test
public void testEnabledBridge()
{
NativeToJsMessageQueue.BridgeMode bridge;
bridge = new NativeToJsMessageQueue.NoOpBridgeMode();
queue.addBridgeMode(bridge);
queue.setBridgeMode(0);
assertTrue(queue.isBridgeEnabled());
}
//This test is for the undocumented encoding system setup for the bridge
//TODO: Document how the non-Javascript bridges are supposed to work
@Test
public void testPopAndEncode()
{
NativeToJsMessageQueue.BridgeMode bridge;
bridge = new NativeToJsMessageQueue.NoOpBridgeMode();
queue.addBridgeMode(bridge);
queue.setBridgeMode(0);
PluginResult result = new PluginResult(PluginResult.Status.OK);
queue.addPluginResult(result, TEST_CALLBACK_ID);
assertFalse(queue.isEmpty());
String resultString = queue.popAndEncode(false);
String [] results = resultString.split(" ");
assertEquals(TEST_CALLBACK_ID, results[2]);
}
//This test is for the evalBridge, which directly calls cordova.callbackFromNative, skipping
//platform specific NativeToJs code
@Test
public void testBasicPopAndEncodeAsJs()
{
NativeToJsMessageQueue.BridgeMode bridge;
bridge = new NativeToJsMessageQueue.NoOpBridgeMode();
queue.addBridgeMode(bridge);
queue.setBridgeMode(0);
PluginResult result = new PluginResult(PluginResult.Status.OK);
queue.addPluginResult(result, TEST_CALLBACK_ID);
assertFalse(queue.isEmpty());
String resultString = queue.popAndEncodeAsJs();
assertTrue(resultString.startsWith("cordova.callbackFromNative"));
}
//This test is for the evalBridge, which directly calls cordova.callbackFromNative, skipping
//platform specific NativeToJs code
@Test
public void testStringPopAndEncodeAsJs()
{
NativeToJsMessageQueue.BridgeMode bridge;
bridge = new NativeToJsMessageQueue.NoOpBridgeMode();
queue.addBridgeMode(bridge);
queue.setBridgeMode(0);
PluginResult result = new PluginResult(PluginResult.Status.OK, "String Plugin Result");
queue.addPluginResult(result, TEST_CALLBACK_ID);
assertFalse(queue.isEmpty());
String resultString = queue.popAndEncodeAsJs();
assertTrue(resultString.startsWith("cordova.callbackFromNative"));
}
//This test is for the evalBridge, which directly calls cordova.callbackFromNative, skipping
//platform specific NativeToJs code
@Test
public void testJsonPopAndEncodeAsJs()
{
NativeToJsMessageQueue.BridgeMode bridge;
bridge = new NativeToJsMessageQueue.NoOpBridgeMode();
queue.addBridgeMode(bridge);
queue.setBridgeMode(0);
JSONObject object = new JSONObject();
try {
object.put("test", "value");
} catch (JSONException e) {
e.printStackTrace();
}
PluginResult result = new PluginResult(PluginResult.Status.OK, object);
queue.addPluginResult(result, TEST_CALLBACK_ID);
assertFalse(queue.isEmpty());
String resultString = queue.popAndEncodeAsJs();
assertTrue(resultString.startsWith("cordova.callbackFromNative"));
}
//This test is for the evalBridge, which directly calls cordova.callbackFromNative, skipping
//platform specific NativeToJs code
@Test
public void testMultipartPopAndEncodeAsJs()
{
ArrayList<PluginResult> multiparts = new ArrayList<PluginResult>();
for (int i=0; i<5; i++) {
multiparts.add(new PluginResult(PluginResult.Status.OK, i));
}
PluginResult multipartresult = new PluginResult(PluginResult.Status.OK, multiparts);
NativeToJsMessageQueue queue = new NativeToJsMessageQueue();
queue.addBridgeMode(new NativeToJsMessageQueue.NoOpBridgeMode());
queue.setBridgeMode(0);
queue.addPluginResult(multipartresult, "37");
String result = queue.popAndEncodeAsJs();
assertEquals(result, "cordova.callbackFromNative('37',true,1,[0,1,2,3,4],false);");
}
@Test
public void testNullPopAndEncodeAsJs()
{
NativeToJsMessageQueue queue = new NativeToJsMessageQueue();
queue.addBridgeMode(new NativeToJsMessageQueue.NoOpBridgeMode());
queue.setBridgeMode(0);
PluginResult result = new PluginResult(PluginResult.Status.OK, (String)null);
queue.addPluginResult(result, TEST_CALLBACK_ID);
assertFalse(queue.isEmpty());
String resultString = queue.popAndEncodeAsJs();
assertEquals(resultString, "cordova.callbackFromNative('" + TEST_CALLBACK_ID + "',true,1,[null],false);");
}
}

View File

@ -0,0 +1,44 @@
/* 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.
*/
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
classpath 'com.android.tools.build:gradle:3.3.0'
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}

View File

@ -0,0 +1,19 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1536m
android.useAndroidX=true
android.enableJetifier=true
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true

Some files were not shown because too many files have changed in this diff Show More