FIX: There was some issue with cordova android 7.0.0 that was preventing the build. going back to 6.2.3
@ -97,5 +97,5 @@
|
||||
<variable name="ANDROID_PATHPREFIX" value="/" />
|
||||
</plugin>
|
||||
<preference name="AndroidLaunchMode" value="singleTask" />
|
||||
<engine name="android" spec="7.0.0" />
|
||||
<engine name="android" spec="6.2.3" />
|
||||
</widget>
|
||||
|
47
DynamicBibleIonic/package-lock.json
generated
@ -2255,25 +2255,20 @@
|
||||
}
|
||||
},
|
||||
"cordova-android": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cordova-android/-/cordova-android-7.0.0.tgz",
|
||||
"integrity": "sha1-yVvt/PvDhjsYDE0p7/7E95Nh0Z0=",
|
||||
"version": "6.2.3",
|
||||
"resolved": "https://registry.npmjs.org/cordova-android/-/cordova-android-6.2.3.tgz",
|
||||
"integrity": "sha1-JJ8hts5fHxyEenq4OxaQnb7Vqig=",
|
||||
"requires": {
|
||||
"android-versions": "1.2.1",
|
||||
"cordova-common": "2.2.0",
|
||||
"cordova-common": "2.0.2",
|
||||
"elementtree": "0.1.6",
|
||||
"nopt": "3.0.6",
|
||||
"properties-parser": "0.2.3",
|
||||
"q": "1.5.1",
|
||||
"q": "1.5.0",
|
||||
"shelljs": "0.5.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"abbrev": {
|
||||
"version": "1.1.1",
|
||||
"bundled": true
|
||||
},
|
||||
"android-versions": {
|
||||
"version": "1.2.1",
|
||||
"version": "1.1.0",
|
||||
"bundled": true
|
||||
},
|
||||
"ansi": {
|
||||
@ -2281,7 +2276,7 @@
|
||||
"bundled": true
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"version": "0.4.2",
|
||||
"bundled": true
|
||||
},
|
||||
"base64-js": {
|
||||
@ -2289,21 +2284,21 @@
|
||||
"bundled": true
|
||||
},
|
||||
"big-integer": {
|
||||
"version": "1.6.26",
|
||||
"version": "1.6.22",
|
||||
"bundled": true
|
||||
},
|
||||
"bplist-parser": {
|
||||
"version": "0.1.1",
|
||||
"bundled": true,
|
||||
"requires": {
|
||||
"big-integer": "1.6.26"
|
||||
"big-integer": "1.6.22"
|
||||
}
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.8",
|
||||
"version": "1.1.7",
|
||||
"bundled": true,
|
||||
"requires": {
|
||||
"balanced-match": "1.0.0",
|
||||
"balanced-match": "0.4.2",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
@ -2312,7 +2307,7 @@
|
||||
"bundled": true
|
||||
},
|
||||
"cordova-common": {
|
||||
"version": "2.2.0",
|
||||
"version": "2.0.2",
|
||||
"bundled": true,
|
||||
"requires": {
|
||||
"ansi": "0.3.1",
|
||||
@ -2320,11 +2315,11 @@
|
||||
"cordova-registry-mapper": "1.1.15",
|
||||
"elementtree": "0.1.6",
|
||||
"glob": "5.0.15",
|
||||
"minimatch": "3.0.4",
|
||||
"minimatch": "3.0.3",
|
||||
"osenv": "0.1.4",
|
||||
"plist": "1.2.0",
|
||||
"q": "1.5.1",
|
||||
"semver": "5.4.1",
|
||||
"q": "1.5.0",
|
||||
"semver": "5.3.0",
|
||||
"shelljs": "0.5.3",
|
||||
"underscore": "1.8.3",
|
||||
"unorm": "1.4.1"
|
||||
@ -2347,7 +2342,7 @@
|
||||
"requires": {
|
||||
"inflight": "1.0.6",
|
||||
"inherits": "2.0.3",
|
||||
"minimatch": "3.0.4",
|
||||
"minimatch": "3.0.3",
|
||||
"once": "1.4.0",
|
||||
"path-is-absolute": "1.0.1"
|
||||
}
|
||||
@ -2369,17 +2364,17 @@
|
||||
"bundled": true
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"version": "3.0.3",
|
||||
"bundled": true,
|
||||
"requires": {
|
||||
"brace-expansion": "1.1.8"
|
||||
"brace-expansion": "1.1.7"
|
||||
}
|
||||
},
|
||||
"nopt": {
|
||||
"version": "3.0.6",
|
||||
"bundled": true,
|
||||
"requires": {
|
||||
"abbrev": "1.1.1"
|
||||
"abbrev": "1.1.0"
|
||||
}
|
||||
},
|
||||
"once": {
|
||||
@ -2424,7 +2419,7 @@
|
||||
"bundled": true
|
||||
},
|
||||
"q": {
|
||||
"version": "1.5.1",
|
||||
"version": "1.5.0",
|
||||
"bundled": true
|
||||
},
|
||||
"sax": {
|
||||
@ -2432,7 +2427,7 @@
|
||||
"bundled": true
|
||||
},
|
||||
"semver": {
|
||||
"version": "5.4.1",
|
||||
"version": "5.3.0",
|
||||
"bundled": true
|
||||
},
|
||||
"shelljs": {
|
||||
|
@ -33,7 +33,7 @@
|
||||
"@ionic-native/status-bar": "4.3.1",
|
||||
"@ionic/storage": "2.1.3",
|
||||
"angularfire2": "^5.0.0-rc.4",
|
||||
"cordova-android": "7.0.0",
|
||||
"cordova-android": "6.2.3",
|
||||
"cordova-plugin-browsertab": "^0.2.0",
|
||||
"cordova-plugin-buildinfo": "^2.0.1",
|
||||
"cordova-plugin-compat": "^1.2.0",
|
||||
|
34
DynamicBibleIonic/platforms/android/AndroidManifest.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<manifest android:hardwareAccelerated="true" android:versionCode="30003" android:versionName="3.0.3" package="walljm.dynamicbible" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<supports-screens android:anyDensity="true" android:largeScreens="true" android:normalScreens="true" android:resizeable="true" android:smallScreens="true" android:xlargeScreens="true"/>
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
||||
<application android:hardwareAccelerated="true" android:icon="@mipmap/icon" android:label="@string/app_name" android:supportsRtl="true">
|
||||
<activity android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale" android:label="@string/activity_name" android:launchMode="singleTask" android:name="MainActivity" android:theme="@android:style/Theme.DeviceDefault.NoActionBar" android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter android:label="@string/launcher_name">
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
<data android:scheme="com.firebase.cordova"/>
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
<data android:host="bhgx5.app.goo.gl/XktS" android:scheme="https"/>
|
||||
</intent-filter>
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
<data android:host="dynamicbible-7c6cf.firebaseapp.com" android:scheme="https" android:path="/__/auth/callback"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="25"/>
|
||||
</manifest>
|
@ -19,5 +19,5 @@
|
||||
-->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.apache.cordova" android:versionName="1.0" android:versionCode="1">
|
||||
<uses-sdk android:minSdkVersion="16" />
|
||||
<uses-sdk android:minSdkVersion="14" />
|
||||
</manifest>
|
||||
|
@ -24,14 +24,12 @@ ext {
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
maven {
|
||||
url "https://maven.google.com"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.0.0'
|
||||
classpath 'com.android.tools.build:gradle:2.2.3'
|
||||
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
|
||||
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3'
|
||||
}
|
||||
@ -42,7 +40,7 @@ apply plugin: 'com.github.dcendents.android-maven'
|
||||
apply plugin: 'com.jfrog.bintray'
|
||||
|
||||
group = 'org.apache.cordova'
|
||||
version = '7.0.0'
|
||||
version = '6.2.3'
|
||||
|
||||
android {
|
||||
compileSdkVersion cdvCompileSdkVersion
|
||||
@ -50,8 +48,8 @@ android {
|
||||
publishNonDefault true
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
sourceCompatibility JavaVersion.VERSION_1_6
|
||||
targetCompatibility JavaVersion.VERSION_1_6
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
@ -129,9 +127,9 @@ bintray {
|
||||
licenses = ['Apache-2.0']
|
||||
labels = ['android', 'cordova', 'phonegap']
|
||||
version {
|
||||
name = '7.0.0'
|
||||
name = '6.2.3'
|
||||
released = new Date()
|
||||
vcsTag = '7.0.0'
|
||||
vcsTag = '6.2.3'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,11 +29,7 @@ String doEnsureValueExists(filePath, props, key) {
|
||||
|
||||
String doGetProjectTarget() {
|
||||
def props = new Properties()
|
||||
def propertiesFile = 'project.properties';
|
||||
if(!(file(propertiesFile).exists())) {
|
||||
propertiesFile = '../project.properties';
|
||||
}
|
||||
file(propertiesFile).withReader { reader ->
|
||||
file('project.properties').withReader { reader ->
|
||||
props.load(reader)
|
||||
}
|
||||
return doEnsureValueExists('project.properties', props, 'target')
|
||||
|
@ -10,7 +10,7 @@
|
||||
# Indicates whether an apk should be generated for each density.
|
||||
split.density=false
|
||||
# Project target.
|
||||
target=android-26
|
||||
target=android-25
|
||||
apk-configurations=
|
||||
renderscript.opt.level=O0
|
||||
android.library=true
|
||||
|
@ -319,7 +319,6 @@ public class CordovaActivity extends Activity {
|
||||
/**
|
||||
* Called when view focus is changed
|
||||
*/
|
||||
@SuppressLint("InlinedApi")
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasFocus) {
|
||||
super.onWindowFocusChanged(hasFocus);
|
||||
|
@ -18,8 +18,6 @@
|
||||
*/
|
||||
package org.apache.cordova;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
|
||||
import org.json.JSONArray;
|
||||
@ -112,9 +110,6 @@ public class CordovaBridge {
|
||||
}
|
||||
|
||||
/** Called by cordova.js to initialize the bridge. */
|
||||
//On old Androids SecureRandom isn't really secure, this is the least of your problems if
|
||||
//you're running Android 4.3 and below in 2017
|
||||
@SuppressLint("TrulyRandom")
|
||||
int generateBridgeSecret() {
|
||||
SecureRandom randGen = new SecureRandom();
|
||||
expectedBridgeSecret = randGen.nextInt(Integer.MAX_VALUE);
|
||||
|
@ -22,12 +22,10 @@ import java.security.Principal;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.webkit.ClientCertRequest;
|
||||
|
||||
/**
|
||||
* Implementation of the ICordovaClientCertRequest for Android WebView.
|
||||
*
|
||||
*/
|
||||
public class CordovaClientCertRequest implements ICordovaClientCertRequest {
|
||||
|
||||
@ -40,7 +38,6 @@ public class CordovaClientCertRequest implements ICordovaClientCertRequest {
|
||||
/**
|
||||
* Cancel this request
|
||||
*/
|
||||
@SuppressLint("NewApi")
|
||||
public void cancel()
|
||||
{
|
||||
request.cancel();
|
||||
@ -49,7 +46,6 @@ public class CordovaClientCertRequest implements ICordovaClientCertRequest {
|
||||
/*
|
||||
* Returns the host name of the server requesting the certificate.
|
||||
*/
|
||||
@SuppressLint("NewApi")
|
||||
public String getHost()
|
||||
{
|
||||
return request.getHost();
|
||||
@ -58,7 +54,6 @@ public class CordovaClientCertRequest implements ICordovaClientCertRequest {
|
||||
/*
|
||||
* Returns the acceptable types of asymmetric keys (can be null).
|
||||
*/
|
||||
@SuppressLint("NewApi")
|
||||
public String[] getKeyTypes()
|
||||
{
|
||||
return request.getKeyTypes();
|
||||
@ -67,7 +62,6 @@ public class CordovaClientCertRequest implements ICordovaClientCertRequest {
|
||||
/*
|
||||
* Returns the port number of the server requesting the certificate.
|
||||
*/
|
||||
@SuppressLint("NewApi")
|
||||
public int getPort()
|
||||
{
|
||||
return request.getPort();
|
||||
@ -76,7 +70,6 @@ public class CordovaClientCertRequest implements ICordovaClientCertRequest {
|
||||
/*
|
||||
* Returns the acceptable certificate issuers for the certificate matching the private key (can be null).
|
||||
*/
|
||||
@SuppressLint("NewApi")
|
||||
public Principal[] getPrincipals()
|
||||
{
|
||||
return request.getPrincipals();
|
||||
@ -85,7 +78,6 @@ public class CordovaClientCertRequest implements ICordovaClientCertRequest {
|
||||
/*
|
||||
* Ignore the request for now. Do not remember user's choice.
|
||||
*/
|
||||
@SuppressLint("NewApi")
|
||||
public void ignore()
|
||||
{
|
||||
request.ignore();
|
||||
@ -97,7 +89,6 @@ public class CordovaClientCertRequest implements ICordovaClientCertRequest {
|
||||
* @param privateKey The privateKey
|
||||
* @param chain The certificate chain
|
||||
*/
|
||||
@SuppressLint("NewApi")
|
||||
public void proceed(PrivateKey privateKey, X509Certificate[] chain)
|
||||
{
|
||||
request.proceed(privateKey, chain);
|
||||
|
@ -19,7 +19,6 @@
|
||||
package org.apache.cordova;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import org.apache.cordova.CordovaPlugin;
|
||||
@ -52,18 +51,10 @@ public interface CordovaInterface {
|
||||
/**
|
||||
* Get the Android activity.
|
||||
*
|
||||
* If a custom engine lives outside of the Activity's lifecycle the return value may be null.
|
||||
*
|
||||
* @return the Activity
|
||||
*/
|
||||
public abstract Activity getActivity();
|
||||
|
||||
/**
|
||||
* Get the Android context.
|
||||
*
|
||||
* @return the Context
|
||||
*/
|
||||
public Context getContext();
|
||||
|
||||
/**
|
||||
* Called when a message is sent to plugin.
|
||||
|
@ -19,9 +19,7 @@
|
||||
|
||||
package org.apache.cordova;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Build;
|
||||
@ -86,11 +84,6 @@ public class CordovaInterfaceImpl implements CordovaInterface {
|
||||
return activity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Context getContext() {
|
||||
return activity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object onMessage(String id, Object data) {
|
||||
if ("exit".equals(id)) {
|
||||
@ -228,7 +221,6 @@ public class CordovaInterfaceImpl implements CordovaInterface {
|
||||
requestPermissions(plugin, requestCode, permissions);
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
public void requestPermissions(CordovaPlugin plugin, int requestCode, String [] permissions) {
|
||||
int mappedRequestCode = permissionResultCallbacks.registerCallback(plugin, requestCode);
|
||||
getActivity().requestPermissions(permissions, mappedRequestCode);
|
||||
|
@ -31,7 +31,7 @@ import android.webkit.WebChromeClient.CustomViewCallback;
|
||||
* are not expected to implement it.
|
||||
*/
|
||||
public interface CordovaWebView {
|
||||
public static final String CORDOVA_VERSION = "7.0.0";
|
||||
public static final String CORDOVA_VERSION = "6.2.3";
|
||||
|
||||
void init(CordovaInterface cordova, List<PluginEntry> pluginEntries, CordovaPreferences preferences);
|
||||
|
||||
|
@ -18,7 +18,6 @@
|
||||
*/
|
||||
package org.apache.cordova;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
@ -92,7 +91,6 @@ public class CordovaWebViewImpl implements CordovaWebView {
|
||||
init(cordova, new ArrayList<PluginEntry>(), new CordovaPreferences());
|
||||
}
|
||||
|
||||
@SuppressLint("Assert")
|
||||
@Override
|
||||
public void init(CordovaInterface cordova, List<PluginEntry> pluginEntries, CordovaPreferences preferences) {
|
||||
if (this.cordova != null) {
|
||||
|
@ -1,87 +0,0 @@
|
||||
/*
|
||||
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;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.json.JSONException;
|
||||
|
||||
import android.content.pm.PackageManager;
|
||||
|
||||
/**
|
||||
* This class provides reflective methods for permission requesting and checking so that plugins
|
||||
* written for cordova-android 5.0.0+ can still compile with earlier cordova-android versions.
|
||||
*/
|
||||
public class PermissionHelper {
|
||||
private static final String LOG_TAG = "CordovaPermissionHelper";
|
||||
|
||||
/**
|
||||
* Requests a "dangerous" permission for the application at runtime. This is a helper method
|
||||
* alternative to cordovaInterface.requestPermission() that does not require the project to be
|
||||
* built with cordova-android 5.0.0+
|
||||
*
|
||||
* @param plugin The plugin the permission is being requested for
|
||||
* @param requestCode A requestCode to be passed to the plugin's onRequestPermissionResult()
|
||||
* along with the result of the permission request
|
||||
* @param permission The permission to be requested
|
||||
*/
|
||||
public static void requestPermission(CordovaPlugin plugin, int requestCode, String permission) {
|
||||
PermissionHelper.requestPermissions(plugin, requestCode, new String[] {permission});
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests "dangerous" permissions for the application at runtime. This is a helper method
|
||||
* alternative to cordovaInterface.requestPermissions() that does not require the project to be
|
||||
* built with cordova-android 5.0.0+
|
||||
*
|
||||
* @param plugin The plugin the permissions are being requested for
|
||||
* @param requestCode A requestCode to be passed to the plugin's onRequestPermissionResult()
|
||||
* along with the result of the permissions request
|
||||
* @param permissions The permissions to be requested
|
||||
*/
|
||||
public static void requestPermissions(CordovaPlugin plugin, int requestCode, String[] permissions) {
|
||||
plugin.cordova.requestPermissions(plugin, requestCode, permissions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks at runtime to see if the application has been granted a permission. This is a helper
|
||||
* method alternative to cordovaInterface.hasPermission() that does not require the project to
|
||||
* be built with cordova-android 5.0.0+
|
||||
*
|
||||
* @param plugin The plugin the permission is being checked against
|
||||
* @param permission The permission to be checked
|
||||
*
|
||||
* @return True if the permission has already been granted and false otherwise
|
||||
*/
|
||||
public static boolean hasPermission(CordovaPlugin plugin, String permission) {
|
||||
return plugin.cordova.hasPermission(permission);
|
||||
}
|
||||
|
||||
private static void deliverPermissionResult(CordovaPlugin plugin, int requestCode, String[] permissions) {
|
||||
// Generate the request results
|
||||
int[] requestResults = new int[permissions.length];
|
||||
Arrays.fill(requestResults, PackageManager.PERMISSION_GRANTED);
|
||||
|
||||
try {
|
||||
plugin.onRequestPermissionResult(requestCode, permissions, requestResults);
|
||||
} catch (JSONException e) {
|
||||
LOG.e(LOG_TAG, "JSONException when delivering permissions results", e);
|
||||
}
|
||||
}
|
||||
}
|
@ -110,12 +110,8 @@ public class SystemWebViewEngine implements CordovaWebViewEngine {
|
||||
nativeToJsMessageQueue.addBridgeMode(new NativeToJsMessageQueue.OnlineEventsBridgeMode(new NativeToJsMessageQueue.OnlineEventsBridgeMode.OnlineEventsBridgeModeDelegate() {
|
||||
@Override
|
||||
public void setNetworkAvailable(boolean value) {
|
||||
//sometimes this can be called after calling webview.destroy() on destroy()
|
||||
//thus resulting in a NullPointerException
|
||||
if(webView!=null) {
|
||||
webView.setNetworkAvailable(value);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void runOnUiThread(Runnable r) {
|
||||
SystemWebViewEngine.this.cordova.getActivity().runOnUiThread(r);
|
||||
@ -214,6 +210,11 @@ public class SystemWebViewEngine implements CordovaWebViewEngine {
|
||||
settings.setAppCachePath(databasePath);
|
||||
settings.setAppCacheEnabled(true);
|
||||
|
||||
// Enable scaling
|
||||
// Fix for CB-12015
|
||||
settings.setUseWideViewPort(true);
|
||||
settings.setLoadWithOverviewMode(true);
|
||||
|
||||
// Fix for CB-1405
|
||||
// Google issue 4641
|
||||
String defaultUserAgent = settings.getUserAgentString();
|
||||
@ -254,9 +255,6 @@ public class SystemWebViewEngine implements CordovaWebViewEngine {
|
||||
}
|
||||
}
|
||||
|
||||
// Yeah, we know, which is why we makes ure that we don't do this if the bridge is
|
||||
// below JELLYBEAN_MR1. It'd be great if lint was just a little smarter.
|
||||
@SuppressLint("AddJavascriptInterface")
|
||||
private static void exposeJsInterface(WebView webView, CordovaBridge bridge) {
|
||||
if ((Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1)) {
|
||||
LOG.i(TAG, "Disabled addJavascriptInterface() bridge since Android version is old.");
|
||||
|
@ -8,6 +8,14 @@
|
||||
"res/xml/config.xml": {
|
||||
"parents": {
|
||||
"/*": [
|
||||
{
|
||||
"xml": "<feature name=\"BrowserTab\"><param name=\"android-package\" value=\"com.google.cordova.plugin.browsertab.BrowserTab\" /></feature>",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"xml": "<feature name=\"BuildInfo\"><param name=\"android-package\" value=\"org.apache.cordova.buildinfo.BuildInfo\" /></feature>",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"xml": "<preference name=\"webView\" value=\"org.crosswalk.engine.XWalkWebViewEngine\" />",
|
||||
"count": 1
|
||||
@ -36,10 +44,18 @@
|
||||
"xml": "<preference name=\"android-minSdkVersion\" value=\"16\" />",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"xml": "<feature name=\"LaunchMyApp\"><param name=\"android-package\" value=\"nl.xservices.plugins.LaunchMyApp\" /></feature>",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"xml": "<feature name=\"Device\"><param name=\"android-package\" value=\"org.apache.cordova.device.Device\" /></feature>",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"xml": "<feature name=\"InAppBrowser\"><param name=\"android-package\" value=\"org.apache.cordova.inappbrowser.InAppBrowser\" /></feature>",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"xml": "<feature name=\"SplashScreen\"><param name=\"android-package\" value=\"org.apache.cordova.splashscreen.SplashScreen\" /><param name=\"onload\" value=\"true\" /></feature>",
|
||||
"count": 1
|
||||
@ -52,28 +68,12 @@
|
||||
"xml": "<feature name=\"Whitelist\"><param name=\"android-package\" value=\"org.apache.cordova.whitelist.WhitelistPlugin\" /><param name=\"onload\" value=\"true\" /></feature>",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"xml": "<feature name=\"Keyboard\"><param name=\"android-package\" value=\"io.ionic.keyboard.IonicKeyboard\" /><param name=\"onload\" value=\"true\" /></feature>",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"xml": "<feature name=\"BuildInfo\"><param name=\"android-package\" value=\"org.apache.cordova.buildinfo.BuildInfo\" /></feature>",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"xml": "<feature name=\"UniversalLinks\"><param name=\"android-package\" value=\"com.nordnetab.cordova.ul.UniversalLinksPlugin\" /><param name=\"onload\" value=\"true\" /></feature>",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"xml": "<feature name=\"BrowserTab\"><param name=\"android-package\" value=\"com.google.cordova.plugin.browsertab.BrowserTab\" /></feature>",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"xml": "<feature name=\"InAppBrowser\"><param name=\"android-package\" value=\"org.apache.cordova.inappbrowser.InAppBrowser\" /></feature>",
|
||||
"count": 1
|
||||
},
|
||||
{
|
||||
"xml": "<feature name=\"LaunchMyApp\"><param name=\"android-package\" value=\"nl.xservices.plugins.LaunchMyApp\" /></feature>",
|
||||
"xml": "<feature name=\"Keyboard\"><param name=\"android-package\" value=\"io.ionic.keyboard.IonicKeyboard\" /><param name=\"onload\" value=\"true\" /></feature>",
|
||||
"count": 1
|
||||
}
|
||||
]
|
||||
@ -106,6 +106,15 @@
|
||||
}
|
||||
},
|
||||
"installed_plugins": {
|
||||
"cordova-plugin-compat": {
|
||||
"PACKAGE_NAME": "walljm.dynamicbible"
|
||||
},
|
||||
"cordova-plugin-browsertab": {
|
||||
"PACKAGE_NAME": "walljm.dynamicbible"
|
||||
},
|
||||
"cordova-plugin-buildinfo": {
|
||||
"PACKAGE_NAME": "walljm.dynamicbible"
|
||||
},
|
||||
"cordova-plugin-console": {
|
||||
"PACKAGE_NAME": "walljm.dynamicbible"
|
||||
},
|
||||
@ -117,9 +126,19 @@
|
||||
"XWALK_MULTIPLEAPK": "true",
|
||||
"PACKAGE_NAME": "walljm.dynamicbible"
|
||||
},
|
||||
"cordova-plugin-customurlscheme": {
|
||||
"URL_SCHEME": "com.firebase.cordova",
|
||||
"ANDROID_SCHEME": " ",
|
||||
"ANDROID_HOST": " ",
|
||||
"ANDROID_PATHPREFIX": "/",
|
||||
"PACKAGE_NAME": "walljm.dynamicbible"
|
||||
},
|
||||
"cordova-plugin-device": {
|
||||
"PACKAGE_NAME": "walljm.dynamicbible"
|
||||
},
|
||||
"cordova-plugin-inappbrowser": {
|
||||
"PACKAGE_NAME": "walljm.dynamicbible"
|
||||
},
|
||||
"cordova-plugin-splashscreen": {
|
||||
"PACKAGE_NAME": "walljm.dynamicbible"
|
||||
},
|
||||
@ -129,31 +148,39 @@
|
||||
"cordova-plugin-whitelist": {
|
||||
"PACKAGE_NAME": "walljm.dynamicbible"
|
||||
},
|
||||
"ionic-plugin-keyboard": {
|
||||
"PACKAGE_NAME": "walljm.dynamicbible"
|
||||
},
|
||||
"cordova-plugin-buildinfo": {
|
||||
"PACKAGE_NAME": "walljm.dynamicbible"
|
||||
},
|
||||
"cordova-universal-links-plugin": {
|
||||
"PACKAGE_NAME": "walljm.dynamicbible"
|
||||
},
|
||||
"cordova-plugin-browsertab": {
|
||||
"PACKAGE_NAME": "walljm.dynamicbible"
|
||||
},
|
||||
"cordova-plugin-inappbrowser": {
|
||||
"PACKAGE_NAME": "walljm.dynamicbible"
|
||||
},
|
||||
"cordova-plugin-customurlscheme": {
|
||||
"URL_SCHEME": "com.firebase.cordova",
|
||||
"ANDROID_SCHEME": " ",
|
||||
"ANDROID_HOST": " ",
|
||||
"ANDROID_PATHPREFIX": "/",
|
||||
"ionic-plugin-keyboard": {
|
||||
"PACKAGE_NAME": "walljm.dynamicbible"
|
||||
}
|
||||
},
|
||||
"dependent_plugins": {},
|
||||
"modules": [
|
||||
{
|
||||
"id": "cordova-plugin-browsertab.BrowserTab",
|
||||
"file": "plugins/cordova-plugin-browsertab/www/browsertab.js",
|
||||
"pluginId": "cordova-plugin-browsertab",
|
||||
"clobbers": [
|
||||
"cordova.plugins.browsertab"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "cordova-plugin-buildinfo.BuildInfo",
|
||||
"file": "plugins/cordova-plugin-buildinfo/www/buildinfo.js",
|
||||
"pluginId": "cordova-plugin-buildinfo",
|
||||
"clobbers": [
|
||||
"BuildInfo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "cordova-plugin-customurlscheme.LaunchMyApp",
|
||||
"file": "plugins/cordova-plugin-customurlscheme/www/android/LaunchMyApp.js",
|
||||
"pluginId": "cordova-plugin-customurlscheme",
|
||||
"clobbers": [
|
||||
"window.plugins.launchmyapp"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "cordova-plugin-device.device",
|
||||
"file": "plugins/cordova-plugin-device/www/device.js",
|
||||
@ -162,6 +189,15 @@
|
||||
"device"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "cordova-plugin-inappbrowser.inappbrowser",
|
||||
"file": "plugins/cordova-plugin-inappbrowser/www/inappbrowser.js",
|
||||
"pluginId": "cordova-plugin-inappbrowser",
|
||||
"clobbers": [
|
||||
"cordova.InAppBrowser.open",
|
||||
"window.open"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "cordova-plugin-splashscreen.SplashScreen",
|
||||
"file": "plugins/cordova-plugin-splashscreen/www/splashscreen.js",
|
||||
@ -178,23 +214,6 @@
|
||||
"window.StatusBar"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "ionic-plugin-keyboard.keyboard",
|
||||
"file": "plugins/ionic-plugin-keyboard/www/android/keyboard.js",
|
||||
"pluginId": "ionic-plugin-keyboard",
|
||||
"clobbers": [
|
||||
"cordova.plugins.Keyboard"
|
||||
],
|
||||
"runs": true
|
||||
},
|
||||
{
|
||||
"id": "cordova-plugin-buildinfo.BuildInfo",
|
||||
"file": "plugins/cordova-plugin-buildinfo/www/buildinfo.js",
|
||||
"pluginId": "cordova-plugin-buildinfo",
|
||||
"clobbers": [
|
||||
"BuildInfo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "cordova-universal-links-plugin.universalLinks",
|
||||
"file": "plugins/cordova-universal-links-plugin/www/universal_links.js",
|
||||
@ -204,43 +223,28 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "cordova-plugin-browsertab.BrowserTab",
|
||||
"file": "plugins/cordova-plugin-browsertab/www/browsertab.js",
|
||||
"pluginId": "cordova-plugin-browsertab",
|
||||
"id": "ionic-plugin-keyboard.keyboard",
|
||||
"file": "plugins/ionic-plugin-keyboard/www/android/keyboard.js",
|
||||
"pluginId": "ionic-plugin-keyboard",
|
||||
"clobbers": [
|
||||
"cordova.plugins.browsertab"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "cordova-plugin-inappbrowser.inappbrowser",
|
||||
"file": "plugins/cordova-plugin-inappbrowser/www/inappbrowser.js",
|
||||
"pluginId": "cordova-plugin-inappbrowser",
|
||||
"clobbers": [
|
||||
"cordova.InAppBrowser.open",
|
||||
"window.open"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "cordova-plugin-customurlscheme.LaunchMyApp",
|
||||
"file": "plugins/cordova-plugin-customurlscheme/www/android/LaunchMyApp.js",
|
||||
"pluginId": "cordova-plugin-customurlscheme",
|
||||
"clobbers": [
|
||||
"window.plugins.launchmyapp"
|
||||
]
|
||||
"cordova.plugins.Keyboard"
|
||||
],
|
||||
"runs": true
|
||||
}
|
||||
],
|
||||
"plugin_metadata": {
|
||||
"cordova-plugin-compat": "1.2.0",
|
||||
"cordova-plugin-browsertab": "0.2.0",
|
||||
"cordova-plugin-buildinfo": "2.0.1",
|
||||
"cordova-plugin-console": "1.1.0",
|
||||
"cordova-plugin-crosswalk-webview": "2.3.0",
|
||||
"cordova-plugin-customurlscheme": "4.3.0",
|
||||
"cordova-plugin-device": "1.1.7",
|
||||
"cordova-plugin-inappbrowser": "2.0.1",
|
||||
"cordova-plugin-splashscreen": "4.1.0",
|
||||
"cordova-plugin-statusbar": "2.4.1",
|
||||
"cordova-plugin-whitelist": "1.3.3",
|
||||
"ionic-plugin-keyboard": "2.2.1",
|
||||
"cordova-plugin-buildinfo": "2.0.1",
|
||||
"cordova-universal-links-plugin": "1.2.1",
|
||||
"cordova-plugin-browsertab": "0.2.0",
|
||||
"cordova-plugin-inappbrowser": "2.0.1",
|
||||
"cordova-plugin-customurlscheme": "4.3.0"
|
||||
"ionic-plugin-keyboard": "2.2.1"
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one
|
||||
/*
|
||||
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
|
||||
@ -16,39 +17,301 @@
|
||||
under the License.
|
||||
*/
|
||||
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
maven {
|
||||
url "https://maven.google.com"
|
||||
}
|
||||
}
|
||||
|
||||
// Switch the Android Gradle plugin version requirement depending on the
|
||||
// installed version of Gradle. This dependency is documented at
|
||||
// http://tools.android.com/tech-docs/new-build-system/version-compatibility
|
||||
// and https://issues.apache.org/jira/browse/CB-8143
|
||||
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.0.0'
|
||||
classpath 'com.android.tools.build:gradle:2.2.3'
|
||||
}
|
||||
}
|
||||
|
||||
// Allow plugins to declare Maven dependencies via build-extras.gradle.
|
||||
allprojects {
|
||||
repositories {
|
||||
mavenCentral();
|
||||
jcenter()
|
||||
maven {
|
||||
url "https://maven.google.com"
|
||||
}
|
||||
}
|
||||
//This replaces project.properties w.r.t. build settings
|
||||
project.ext {
|
||||
defaultBuildToolsVersion="25.0.2" //String
|
||||
defaultMinSdkVersion=19 //Integer - Minimum requirement is Android 4.4
|
||||
defaultTargetSdkVersion=26 //Integer - We ALWAYS target the latest by default
|
||||
defaultCompileSdkVersion=26 //Integer - We ALWAYS compile with the latest by default
|
||||
}
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
delete rootProject.buildDir
|
||||
task wrapper(type: Wrapper) {
|
||||
gradleVersion = '2.14.1'
|
||||
}
|
||||
|
||||
// Configuration properties. Set these via environment variables, build-extras.gradle, or gradle.properties.
|
||||
// Refer to: http://www.gradle.org/docs/current/userguide/tutorial_this_and_that.html
|
||||
ext {
|
||||
apply from: 'CordovaLib/cordova.gradle'
|
||||
// The value for android.compileSdkVersion.
|
||||
if (!project.hasProperty('cdvCompileSdkVersion')) {
|
||||
cdvCompileSdkVersion = null;
|
||||
}
|
||||
// The value for android.buildToolsVersion.
|
||||
if (!project.hasProperty('cdvBuildToolsVersion')) {
|
||||
cdvBuildToolsVersion = null;
|
||||
}
|
||||
// Sets the versionCode to the given value.
|
||||
if (!project.hasProperty('cdvVersionCode')) {
|
||||
cdvVersionCode = null
|
||||
}
|
||||
// Sets the minSdkVersion to the given value.
|
||||
if (!project.hasProperty('cdvMinSdkVersion')) {
|
||||
cdvMinSdkVersion = null
|
||||
}
|
||||
// Whether to build architecture-specific APKs.
|
||||
if (!project.hasProperty('cdvBuildMultipleApks')) {
|
||||
cdvBuildMultipleApks = null
|
||||
}
|
||||
// .properties files to use for release signing.
|
||||
if (!project.hasProperty('cdvReleaseSigningPropertiesFile')) {
|
||||
cdvReleaseSigningPropertiesFile = null
|
||||
}
|
||||
// .properties files to use for debug signing.
|
||||
if (!project.hasProperty('cdvDebugSigningPropertiesFile')) {
|
||||
cdvDebugSigningPropertiesFile = null
|
||||
}
|
||||
// Set by build.js script.
|
||||
if (!project.hasProperty('cdvBuildArch')) {
|
||||
cdvBuildArch = null
|
||||
}
|
||||
|
||||
// Plugin gradle extensions can append to this to have code run at the end.
|
||||
cdvPluginPostBuildExtras = []
|
||||
}
|
||||
|
||||
// PLUGIN GRADLE EXTENSIONS START
|
||||
apply from: "cordova-plugin-browsertab/dynamicbible-BrowserTab.gradle"
|
||||
apply from: "cordova-plugin-buildinfo/dynamicbible-BuildInfo.gradle"
|
||||
apply from: "cordova-plugin-crosswalk-webview/dynamicbible-xwalk.gradle"
|
||||
// PLUGIN GRADLE EXTENSIONS END
|
||||
|
||||
def hasBuildExtras = file('build-extras.gradle').exists()
|
||||
if (hasBuildExtras) {
|
||||
apply from: 'build-extras.gradle'
|
||||
}
|
||||
|
||||
// Set property defaults after extension .gradle files.
|
||||
if (ext.cdvCompileSdkVersion == null) {
|
||||
ext.cdvCompileSdkVersion = privateHelpers.getProjectTarget()
|
||||
}
|
||||
if (ext.cdvBuildToolsVersion == null) {
|
||||
ext.cdvBuildToolsVersion = privateHelpers.findLatestInstalledBuildTools()
|
||||
}
|
||||
if (ext.cdvDebugSigningPropertiesFile == null && file('debug-signing.properties').exists()) {
|
||||
ext.cdvDebugSigningPropertiesFile = 'debug-signing.properties'
|
||||
}
|
||||
if (ext.cdvReleaseSigningPropertiesFile == null && file('release-signing.properties').exists()) {
|
||||
ext.cdvReleaseSigningPropertiesFile = 'release-signing.properties'
|
||||
}
|
||||
|
||||
// Cast to appropriate types.
|
||||
ext.cdvBuildMultipleApks = cdvBuildMultipleApks == null ? false : cdvBuildMultipleApks.toBoolean();
|
||||
ext.cdvMinSdkVersion = cdvMinSdkVersion == null ? null : Integer.parseInt('' + cdvMinSdkVersion)
|
||||
ext.cdvVersionCode = cdvVersionCode == null ? null : Integer.parseInt('' + cdvVersionCode)
|
||||
|
||||
def computeBuildTargetName(debugBuild) {
|
||||
def ret = 'assemble'
|
||||
if (cdvBuildMultipleApks && cdvBuildArch) {
|
||||
def arch = cdvBuildArch == 'arm' ? 'armv7' : cdvBuildArch
|
||||
ret += '' + arch.toUpperCase().charAt(0) + arch.substring(1);
|
||||
}
|
||||
return ret + (debugBuild ? 'Debug' : 'Release')
|
||||
}
|
||||
|
||||
// Make cdvBuild a task that depends on the debug/arch-sepecific task.
|
||||
task cdvBuildDebug
|
||||
cdvBuildDebug.dependsOn {
|
||||
return computeBuildTargetName(true)
|
||||
}
|
||||
|
||||
task cdvBuildRelease
|
||||
cdvBuildRelease.dependsOn {
|
||||
return computeBuildTargetName(false)
|
||||
}
|
||||
|
||||
task cdvPrintProps << {
|
||||
println('cdvCompileSdkVersion=' + cdvCompileSdkVersion)
|
||||
println('cdvBuildToolsVersion=' + cdvBuildToolsVersion)
|
||||
println('cdvVersionCode=' + cdvVersionCode)
|
||||
println('cdvMinSdkVersion=' + cdvMinSdkVersion)
|
||||
println('cdvBuildMultipleApks=' + cdvBuildMultipleApks)
|
||||
println('cdvReleaseSigningPropertiesFile=' + cdvReleaseSigningPropertiesFile)
|
||||
println('cdvDebugSigningPropertiesFile=' + cdvDebugSigningPropertiesFile)
|
||||
println('cdvBuildArch=' + cdvBuildArch)
|
||||
println('computedVersionCode=' + android.defaultConfig.versionCode)
|
||||
android.productFlavors.each { flavor ->
|
||||
println('computed' + flavor.name.capitalize() + 'VersionCode=' + flavor.versionCode)
|
||||
}
|
||||
}
|
||||
|
||||
android {
|
||||
sourceSets {
|
||||
main {
|
||||
manifest.srcFile 'AndroidManifest.xml'
|
||||
java.srcDirs = ['src']
|
||||
resources.srcDirs = ['src']
|
||||
aidl.srcDirs = ['src']
|
||||
renderscript.srcDirs = ['src']
|
||||
res.srcDirs = ['res']
|
||||
assets.srcDirs = ['assets']
|
||||
jniLibs.srcDirs = ['libs']
|
||||
}
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
versionCode cdvVersionCode ?: new BigInteger("" + privateHelpers.extractIntFromManifest("versionCode"))
|
||||
applicationId privateHelpers.extractStringFromManifest("package")
|
||||
|
||||
if (cdvMinSdkVersion != null) {
|
||||
minSdkVersion cdvMinSdkVersion
|
||||
}
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
abortOnError false;
|
||||
}
|
||||
|
||||
compileSdkVersion cdvCompileSdkVersion
|
||||
buildToolsVersion cdvBuildToolsVersion
|
||||
|
||||
if (Boolean.valueOf(cdvBuildMultipleApks)) {
|
||||
productFlavors {
|
||||
armv7 {
|
||||
versionCode defaultConfig.versionCode*10 + 2
|
||||
ndk {
|
||||
abiFilters "armeabi-v7a", ""
|
||||
}
|
||||
}
|
||||
x86 {
|
||||
versionCode defaultConfig.versionCode*10 + 4
|
||||
ndk {
|
||||
abiFilters "x86", ""
|
||||
}
|
||||
}
|
||||
all {
|
||||
ndk {
|
||||
abiFilters "all", ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
||||
ELSE NOTHING! DON'T MESS WITH THE VERSION CODE IF YOU DON'T HAVE TO!
|
||||
|
||||
else if (!cdvVersionCode) {
|
||||
def minSdkVersion = cdvMinSdkVersion ?: privateHelpers.extractIntFromManifest("minSdkVersion")
|
||||
// Vary versionCode by the two most common API levels:
|
||||
// 14 is ICS, which is the lowest API level for many apps.
|
||||
// 20 is Lollipop, which is the lowest API level for the updatable system webview.
|
||||
if (minSdkVersion >= 20) {
|
||||
defaultConfig.versionCode += 9
|
||||
} else if (minSdkVersion >= 14) {
|
||||
defaultConfig.versionCode += 8
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_6
|
||||
targetCompatibility JavaVersion.VERSION_1_6
|
||||
}
|
||||
|
||||
if (cdvReleaseSigningPropertiesFile) {
|
||||
signingConfigs {
|
||||
release {
|
||||
// These must be set or Gradle will complain (even if they are overridden).
|
||||
keyAlias = ""
|
||||
keyPassword = "__unset" // And these must be set to non-empty in order to have the signing step added to the task graph.
|
||||
storeFile = null
|
||||
storePassword = "__unset"
|
||||
}
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
signingConfig signingConfigs.release
|
||||
}
|
||||
}
|
||||
addSigningProps(cdvReleaseSigningPropertiesFile, signingConfigs.release)
|
||||
}
|
||||
if (cdvDebugSigningPropertiesFile) {
|
||||
addSigningProps(cdvDebugSigningPropertiesFile, signingConfigs.debug)
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: '*.jar')
|
||||
// SUB-PROJECT DEPENDENCIES START
|
||||
debugCompile(project(path: "CordovaLib", configuration: "debug"))
|
||||
releaseCompile(project(path: "CordovaLib", configuration: "release"))
|
||||
compile "com.android.support:customtabs:23.3.0"
|
||||
// SUB-PROJECT DEPENDENCIES END
|
||||
}
|
||||
|
||||
def promptForReleaseKeyPassword() {
|
||||
if (!cdvReleaseSigningPropertiesFile) {
|
||||
return;
|
||||
}
|
||||
if ('__unset'.equals(android.signingConfigs.release.storePassword)) {
|
||||
android.signingConfigs.release.storePassword = privateHelpers.promptForPassword('Enter key store password: ')
|
||||
}
|
||||
if ('__unset'.equals(android.signingConfigs.release.keyPassword)) {
|
||||
android.signingConfigs.release.keyPassword = privateHelpers.promptForPassword('Enter key password: ');
|
||||
}
|
||||
}
|
||||
|
||||
gradle.taskGraph.whenReady { taskGraph ->
|
||||
taskGraph.getAllTasks().each() { task ->
|
||||
if (task.name == 'validateReleaseSigning' || task.name == 'validateSigningRelease') {
|
||||
promptForReleaseKeyPassword()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def addSigningProps(propsFilePath, signingConfig) {
|
||||
def propsFile = file(propsFilePath)
|
||||
def props = new Properties()
|
||||
propsFile.withReader { reader ->
|
||||
props.load(reader)
|
||||
}
|
||||
|
||||
def storeFile = new File(props.get('key.store') ?: privateHelpers.ensureValueExists(propsFilePath, props, 'storeFile'))
|
||||
if (!storeFile.isAbsolute()) {
|
||||
storeFile = RelativePath.parse(true, storeFile.toString()).getFile(propsFile.getParentFile())
|
||||
}
|
||||
if (!storeFile.exists()) {
|
||||
throw new FileNotFoundException('Keystore file does not exist: ' + storeFile.getAbsolutePath())
|
||||
}
|
||||
signingConfig.keyAlias = props.get('key.alias') ?: privateHelpers.ensureValueExists(propsFilePath, props, 'keyAlias')
|
||||
signingConfig.keyPassword = props.get('keyPassword', props.get('key.alias.password', signingConfig.keyPassword))
|
||||
signingConfig.storeFile = storeFile
|
||||
signingConfig.storePassword = props.get('storePassword', props.get('key.store.password', signingConfig.storePassword))
|
||||
def storeType = props.get('storeType', props.get('key.store.type', ''))
|
||||
if (!storeType) {
|
||||
def filename = storeFile.getName().toLowerCase();
|
||||
if (filename.endsWith('.p12') || filename.endsWith('.pfx')) {
|
||||
storeType = 'pkcs12'
|
||||
} else {
|
||||
storeType = signingConfig.storeType // "jks"
|
||||
}
|
||||
}
|
||||
signingConfig.storeType = storeType
|
||||
}
|
||||
|
||||
for (def func : cdvPluginPostBuildExtras) {
|
||||
func()
|
||||
}
|
||||
|
||||
// This can be defined within build-extras.gradle as:
|
||||
// ext.postBuildExtras = { ... code here ... }
|
||||
if (hasProperty('postBuildExtras')) {
|
||||
postBuildExtras()
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ def DEFAULT_MIN_SDK_VERSION = 14
|
||||
|
||||
def getConfigPreference(name) {
|
||||
name = name.toLowerCase()
|
||||
def xml = file("src/main/res/xml/config.xml").getText()
|
||||
def xml = file("res/xml/config.xml").getText()
|
||||
// Disable namespace awareness since Cordova doesn't use them properly
|
||||
def root = new XmlParser(false, false).parseText(xml)
|
||||
|
||||
|
10
DynamicBibleIonic/platforms/android/cordova/.jshintrc
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"node": true
|
||||
, "bitwise": true
|
||||
, "undef": true
|
||||
, "trailing": true
|
||||
, "quotmark": true
|
||||
, "indent": 4
|
||||
, "unused": "vars"
|
||||
, "latedef": "nofunc"
|
||||
}
|
@ -29,6 +29,7 @@ var selfEvents = require('cordova-common').events;
|
||||
|
||||
var PLATFORM = 'android';
|
||||
|
||||
|
||||
function setupEvents(externalEventEmitter) {
|
||||
if (externalEventEmitter) {
|
||||
// This will make the platform internal events visible outside
|
||||
@ -42,6 +43,7 @@ function setupEvents (externalEventEmitter) {
|
||||
return selfEvents;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class, that acts as abstraction over particular platform. Encapsulates the
|
||||
* platform's properties and methods.
|
||||
@ -56,7 +58,6 @@ function setupEvents (externalEventEmitter) {
|
||||
function Api(platform, platformRootDir, events) {
|
||||
this.platform = PLATFORM;
|
||||
this.root = path.resolve(__dirname, '..');
|
||||
this.builder = 'gradle';
|
||||
|
||||
setupEvents(events);
|
||||
|
||||
@ -72,7 +73,6 @@ function Api (platform, platformRootDir, events) {
|
||||
strings: path.join(self.root, 'res/values/strings.xml'),
|
||||
manifest: path.join(self.root, 'AndroidManifest.xml'),
|
||||
build: path.join(self.root, 'build'),
|
||||
javaSrc: path.join(self.root, 'src'),
|
||||
// NOTE: Due to platformApi spec we need to return relative paths here
|
||||
cordovaJs: 'bin/templates/project/assets/www/cordova.js',
|
||||
cordovaJsSrc: 'cordova-js-src'
|
||||
@ -81,13 +81,10 @@ function Api (platform, platformRootDir, events) {
|
||||
// XXX Override some locations for Android Studio projects
|
||||
if(AndroidStudio.isAndroidStudioProject(self.root) === true) {
|
||||
selfEvents.emit('log', 'Android Studio project detected');
|
||||
this.builder = 'studio';
|
||||
this.android_studio = true;
|
||||
this.locations.configXml = path.join(self.root, 'app/src/main/res/xml/config.xml');
|
||||
this.locations.strings = path.join(self.root, 'app/src/main/res/values/strings.xml');
|
||||
this.locations.strings = path.join(self.root, 'app/src/main/res/xml/strings.xml');
|
||||
this.locations.manifest = path.join(self.root, 'app/src/main/AndroidManifest.xml');
|
||||
// We could have Java Source, we could have other languages
|
||||
this.locations.javaSrc = path.join(self.root, 'app/src/main/java/');
|
||||
this.locations.www = path.join(self.root, 'app/src/main/assets/www');
|
||||
this.locations.res = path.join(self.root, 'app/src/main/res');
|
||||
}
|
||||
@ -115,11 +112,14 @@ Api.createPlatform = function (destination, config, options, events) {
|
||||
events = setupEvents(events);
|
||||
var result;
|
||||
try {
|
||||
result = require('../../lib/create').create(destination, config, options, events).then(function (destination) {
|
||||
result = require('../../lib/create')
|
||||
.create(destination, config, options, events)
|
||||
.then(function (destination) {
|
||||
var PlatformApi = require(path.resolve(destination, 'cordova/Api'));
|
||||
return new PlatformApi(PLATFORM, destination, events);
|
||||
});
|
||||
} catch (e) {
|
||||
}
|
||||
catch (e) {
|
||||
events.emit('error','createPlatform is not callable from the android project API.');
|
||||
throw(e);
|
||||
}
|
||||
@ -146,11 +146,14 @@ Api.updatePlatform = function (destination, options, events) {
|
||||
events = setupEvents(events);
|
||||
var result;
|
||||
try {
|
||||
result = require('../../lib/create').update(destination, options, events).then(function (destination) {
|
||||
result = require('../../lib/create')
|
||||
.update(destination, options, events)
|
||||
.then(function (destination) {
|
||||
var PlatformApi = require(path.resolve(destination, 'cordova/Api'));
|
||||
return new PlatformApi('android', destination, events);
|
||||
});
|
||||
} catch (e) {
|
||||
}
|
||||
catch (e) {
|
||||
events.emit('error','updatePlatform is not callable from the android project API, you will need to do this manually.');
|
||||
throw(e);
|
||||
}
|
||||
@ -227,10 +230,12 @@ Api.prototype.addPlugin = function (plugin, installOptions) {
|
||||
installOptions.android_studio = true;
|
||||
}
|
||||
|
||||
return Q().then(function () {
|
||||
return Q()
|
||||
.then(function () {
|
||||
//CB-11964: Do a clean when installing the plugin code to get around
|
||||
//the Gradle bug introduced by the Android Gradle Plugin Version 2.2
|
||||
//TODO: Delete when the next version of Android Gradle plugin comes out
|
||||
|
||||
// Since clean doesn't just clean the build, it also wipes out www, we need
|
||||
// to pass additional options.
|
||||
|
||||
@ -243,13 +248,16 @@ Api.prototype.addPlugin = function (plugin, installOptions) {
|
||||
if(!AndroidStudio.isAndroidStudioProject(self.root) && !project.isClean()) {
|
||||
return self.clean(opts);
|
||||
}
|
||||
}).then(function () {
|
||||
return PluginManager.get(self.platform, self.locations, project).addPlugin(plugin, installOptions);
|
||||
}).then(function () {
|
||||
})
|
||||
.then(function () {
|
||||
return PluginManager.get(self.platform, self.locations, project)
|
||||
.addPlugin(plugin, installOptions);
|
||||
})
|
||||
.then(function () {
|
||||
if (plugin.getFrameworks(this.platform).length === 0) return;
|
||||
|
||||
selfEvents.emit('verbose', 'Updating build files since android plugin contained <framework>');
|
||||
// This should pick the correct builder, not just get gradle
|
||||
require('./lib/builders/builders').getBuilder(this.builder).prepBuildFiles();
|
||||
require('./lib/builders/builders').getBuilder('gradle').prepBuildFiles();
|
||||
}.bind(this))
|
||||
// CB-11022 Return truthy value to prevent running prepare after
|
||||
.thenResolve(true);
|
||||
@ -282,7 +290,7 @@ Api.prototype.removePlugin = function (plugin, uninstallOptions) {
|
||||
if (plugin.getFrameworks(this.platform).length === 0) return;
|
||||
|
||||
selfEvents.emit('verbose', 'Updating build files since android plugin contained <framework>');
|
||||
require('./lib/builders/builders').getBuilder(this.builder).prepBuildFiles();
|
||||
require('./lib/builders/builders').getBuilder('gradle').prepBuildFiles();
|
||||
}.bind(this))
|
||||
// CB-11022 Return truthy value to prevent running prepare after
|
||||
.thenResolve(true);
|
||||
@ -335,12 +343,11 @@ Api.prototype.removePlugin = function (plugin, uninstallOptions) {
|
||||
*/
|
||||
Api.prototype.build = function (buildOptions) {
|
||||
var self = this;
|
||||
if (this.android_studio) {
|
||||
buildOptions.studio = true;
|
||||
}
|
||||
return require('./lib/check_reqs').run().then(function () {
|
||||
return require('./lib/check_reqs').run()
|
||||
.then(function () {
|
||||
return require('./lib/build').run.call(self, buildOptions);
|
||||
}).then(function (buildResults) {
|
||||
})
|
||||
.then(function (buildResults) {
|
||||
// Cast build result to array of build artifacts
|
||||
return buildResults.apkPaths.map(function (apkPath) {
|
||||
return {
|
||||
@ -367,7 +374,8 @@ Api.prototype.build = function (buildOptions) {
|
||||
*/
|
||||
Api.prototype.run = function(runOptions) {
|
||||
var self = this;
|
||||
return require('./lib/check_reqs').run().then(function () {
|
||||
return require('./lib/check_reqs').run()
|
||||
.then(function () {
|
||||
return require('./lib/run').run.call(self, runOptions);
|
||||
});
|
||||
};
|
||||
@ -381,21 +389,17 @@ Api.prototype.run = function (runOptions) {
|
||||
*/
|
||||
Api.prototype.clean = function(cleanOptions) {
|
||||
var self = this;
|
||||
if (this.android_studio) {
|
||||
// This will lint, checking for null won't
|
||||
if (typeof cleanOptions === 'undefined') {
|
||||
cleanOptions = {};
|
||||
}
|
||||
cleanOptions.studio = true;
|
||||
}
|
||||
|
||||
return require('./lib/check_reqs').run().then(function () {
|
||||
return require('./lib/check_reqs').run()
|
||||
.then(function () {
|
||||
return require('./lib/build').runClean.call(self, cleanOptions);
|
||||
}).then(function () {
|
||||
})
|
||||
.then(function () {
|
||||
return require('./lib/prepare').clean.call(self, cleanOptions);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Performs a requirements check for current platform. Each platform defines its
|
||||
* own set of requirements, which should be resolved before platform can be
|
||||
|
@ -18,7 +18,7 @@
|
||||
@ECHO OFF
|
||||
SET script_path="%~dp0android_sdk_version"
|
||||
IF EXIST %script_path% (
|
||||
node %script_path% %*
|
||||
node "%script_path%" %*
|
||||
) ELSE (
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'android_sdk_version' script in 'bin' folder, aborting...>&2
|
||||
|
@ -18,7 +18,7 @@
|
||||
@ECHO OFF
|
||||
SET script_path="%~dp0check_reqs"
|
||||
IF EXIST %script_path% (
|
||||
node %script_path% %*
|
||||
node "%script_path%" %*
|
||||
) ELSE (
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'check_reqs' script in 'bin' folder, aborting...>&2
|
||||
|
@ -44,7 +44,8 @@ function isEmulator (line) {
|
||||
* devices/emulators
|
||||
*/
|
||||
Adb.devices = function (opts) {
|
||||
return spawn('adb', ['devices'], {cwd: os.tmpdir()}).then(function (output) {
|
||||
return spawn('adb', ['devices'], {cwd: os.tmpdir()})
|
||||
.then(function(output) {
|
||||
return output.split('\n').filter(function (line) {
|
||||
// Filter out either real devices or emulators, depending on options
|
||||
return (line && opts && opts.emulators) ? isEmulator(line) : isDevice(line);
|
||||
@ -58,7 +59,8 @@ Adb.install = function (target, packagePath, opts) {
|
||||
events.emit('verbose', 'Installing apk ' + packagePath + ' on target ' + target + '...');
|
||||
var args = ['-s', target, 'install'];
|
||||
if (opts && opts.replace) args.push('-r');
|
||||
return spawn('adb', args.concat(packagePath), {cwd: os.tmpdir()}).then(function (output) {
|
||||
return spawn('adb', args.concat(packagePath), {cwd: os.tmpdir()})
|
||||
.then(function(output) {
|
||||
// 'adb install' seems to always returns no error, even if installation fails
|
||||
// so we catching output to detect installation failure
|
||||
if (output.match(/Failure/)) {
|
||||
@ -84,7 +86,8 @@ Adb.shell = function (target, shellCommand) {
|
||||
events.emit('verbose', 'Running adb shell command "' + shellCommand + '" on target ' + target + '...');
|
||||
var args = ['-s', target, 'shell'];
|
||||
shellCommand = shellCommand.split(/\s+/);
|
||||
return spawn('adb', args.concat(shellCommand), {cwd: os.tmpdir()}).catch(function (output) {
|
||||
return spawn('adb', args.concat(shellCommand), {cwd: os.tmpdir()})
|
||||
.catch(function (output) {
|
||||
return Q.reject(new CordovaError('Failed to execute shell command "' +
|
||||
shellCommand + '"" on device: ' + output));
|
||||
});
|
||||
@ -92,7 +95,8 @@ Adb.shell = function (target, shellCommand) {
|
||||
|
||||
Adb.start = function (target, activityName) {
|
||||
events.emit('verbose', 'Starting application "' + activityName + '" on target ' + target + '...');
|
||||
return Adb.shell(target, 'am start -W -a android.intent.action.MAIN -n' + activityName).catch(function (output) {
|
||||
return Adb.shell(target, 'am start -W -a android.intent.action.MAIN -n' + activityName)
|
||||
.catch(function (output) {
|
||||
return Q.reject(new CordovaError('Failed to start application "' +
|
||||
activityName + '"" on device: ' + output));
|
||||
});
|
||||
|
@ -102,7 +102,8 @@ AndroidManifest.prototype.getActivity = function () {
|
||||
};
|
||||
};
|
||||
|
||||
['minSdkVersion', 'maxSdkVersion', 'targetSdkVersion'].forEach(function (sdkPrefName) {
|
||||
['minSdkVersion', 'maxSdkVersion', 'targetSdkVersion']
|
||||
.forEach(function(sdkPrefName) {
|
||||
// Copy variable reference to avoid closure issues
|
||||
var prefName = sdkPrefName;
|
||||
|
||||
|
@ -28,7 +28,8 @@ var projectFileCache = {};
|
||||
|
||||
function addToPropertyList(projectProperties, key, value) {
|
||||
var i = 1;
|
||||
while (projectProperties.get(key + '.' + i)) { i++; }
|
||||
while (projectProperties.get(key + '.' + i))
|
||||
i++;
|
||||
|
||||
projectProperties.set(key + '.' + i, value);
|
||||
projectProperties.dirty = true;
|
||||
@ -53,7 +54,7 @@ function removeFromPropertyList (projectProperties, key, value) {
|
||||
|
||||
function getRelativeLibraryPath (parentDir, subDir) {
|
||||
var libraryPath = path.relative(parentDir, subDir);
|
||||
return (path.sep === '\\') ? libraryPath.replace(/\\/g, '/') : libraryPath;
|
||||
return (path.sep == '\\') ? libraryPath.replace(/\\/g, '/') : libraryPath;
|
||||
}
|
||||
|
||||
function AndroidProject(projectDir) {
|
||||
|
@ -11,8 +11,8 @@ var fs = require('fs');
|
||||
var CordovaError = require('cordova-common').CordovaError;
|
||||
|
||||
module.exports.isAndroidStudioProject = function isAndroidStudioProject(root) {
|
||||
var eclipseFiles = ['AndroidManifest.xml', 'libs', 'res'];
|
||||
var androidStudioFiles = ['app', 'app/src/main'];
|
||||
var eclipseFiles = ['AndroidManifest.xml', 'libs', 'res', 'project.properties', 'platform_www'];
|
||||
var androidStudioFiles = ['app', 'gradle', 'app/src/main/res'];
|
||||
|
||||
// assume it is an AS project and not an Eclipse project
|
||||
var isEclipse = false;
|
||||
|
@ -17,8 +17,8 @@
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var Q = require('q');
|
||||
var superspawn = require('cordova-common').superspawn;
|
||||
var Q = require('q'),
|
||||
superspawn = require('cordova-common').superspawn;
|
||||
|
||||
var suffix_number_regex = /(\d+)$/;
|
||||
// Used for sorting Android targets, example strings to sort:
|
||||
@ -44,7 +44,8 @@ function sort_by_largest_numerical_suffix (a, b) {
|
||||
}
|
||||
|
||||
module.exports.print_newest_available_sdk_target = function() {
|
||||
return module.exports.list_targets().then(function (targets) {
|
||||
return module.exports.list_targets()
|
||||
.then(function(targets) {
|
||||
targets.sort(sort_by_largest_numerical_suffix);
|
||||
console.log(targets[0]);
|
||||
});
|
||||
@ -77,22 +78,26 @@ function parse_targets (output) {
|
||||
}
|
||||
|
||||
module.exports.list_targets_with_android = function() {
|
||||
return superspawn.spawn('android', ['list', 'target']).then(parse_targets);
|
||||
return superspawn.spawn('android', ['list', 'target'])
|
||||
.then(parse_targets);
|
||||
};
|
||||
|
||||
module.exports.list_targets_with_avdmanager = function() {
|
||||
return superspawn.spawn('avdmanager', ['list', 'target']).then(parse_targets);
|
||||
return superspawn.spawn('avdmanager', ['list', 'target'])
|
||||
.then(parse_targets);
|
||||
};
|
||||
|
||||
module.exports.list_targets = function() {
|
||||
return module.exports.list_targets_with_avdmanager().catch(function (err) {
|
||||
return module.exports.list_targets_with_avdmanager()
|
||||
.catch(function(err) {
|
||||
// If there's an error, like avdmanager could not be found, we can try
|
||||
// as a last resort, to run `android`, in case this is a super old
|
||||
// SDK installation.
|
||||
if (err && (err.code === 'ENOENT' || (err.stderr && err.stderr.match(/not recognized/)))) {
|
||||
if (err && (err.code == 'ENOENT' || (err.stderr && err.stderr.match(/not recognized/)))) {
|
||||
return module.exports.list_targets_with_android();
|
||||
} else throw err;
|
||||
}).then(function (targets) {
|
||||
})
|
||||
.then(function(targets) {
|
||||
if (targets.length === 0) {
|
||||
return Q.reject(new Error('No android targets (SDKs) installed!'));
|
||||
}
|
||||
|
@ -19,10 +19,10 @@
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var Q = require('q');
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var nopt = require('nopt');
|
||||
var Q = require('q'),
|
||||
path = require('path'),
|
||||
fs = require('fs'),
|
||||
nopt = require('nopt');
|
||||
|
||||
var Adb = require('./Adb');
|
||||
|
||||
@ -35,7 +35,7 @@ function parseOpts (options, resolvedTarget, projectRoot) {
|
||||
options = options || {};
|
||||
options.argv = nopt({
|
||||
gradle: Boolean,
|
||||
studio: Boolean,
|
||||
ant: Boolean,
|
||||
prepenv: Boolean,
|
||||
versionCode: String,
|
||||
minSdkVersion: String,
|
||||
@ -47,28 +47,24 @@ function parseOpts (options, resolvedTarget, projectRoot) {
|
||||
keystoreType: String
|
||||
}, {}, options.argv, 0);
|
||||
|
||||
// Android Studio Build method is the default
|
||||
var ret = {
|
||||
buildType: options.release ? 'release' : 'debug',
|
||||
buildMethod: process.env.ANDROID_BUILD || 'studio',
|
||||
buildMethod: process.env.ANDROID_BUILD || 'gradle',
|
||||
prepEnv: options.argv.prepenv,
|
||||
arch: resolvedTarget && resolvedTarget.arch,
|
||||
extraArgs: []
|
||||
};
|
||||
|
||||
if (options.argv.gradle || options.argv.studio) {
|
||||
ret.buildMethod = options.argv.studio ? 'studio' : 'gradle';
|
||||
}
|
||||
|
||||
// This comes from cordova/run
|
||||
if (options.studio) ret.buildMethod = 'studio';
|
||||
if (options.gradle) ret.buildMethod = 'gradle';
|
||||
if (options.argv.ant || options.argv.gradle)
|
||||
ret.buildMethod = options.argv.ant ? 'ant' : 'gradle';
|
||||
|
||||
if (options.nobuild) ret.buildMethod = 'none';
|
||||
|
||||
if (options.argv.versionCode) { ret.extraArgs.push('-PcdvVersionCode=' + options.argv.versionCode); }
|
||||
if (options.argv.versionCode)
|
||||
ret.extraArgs.push('-PcdvVersionCode=' + options.argv.versionCode);
|
||||
|
||||
if (options.argv.minSdkVersion) { ret.extraArgs.push('-PcdvMinSdkVersion=' + options.argv.minSdkVersion); }
|
||||
if (options.argv.minSdkVersion)
|
||||
ret.extraArgs.push('-PcdvMinSdkVersion=' + options.argv.minSdkVersion);
|
||||
|
||||
if (options.argv.gradleArg) {
|
||||
ret.extraArgs = ret.extraArgs.concat(options.argv.gradleArg);
|
||||
@ -76,10 +72,12 @@ function parseOpts (options, resolvedTarget, projectRoot) {
|
||||
|
||||
var packageArgs = {};
|
||||
|
||||
if (options.argv.keystore) { packageArgs.keystore = path.relative(projectRoot, path.resolve(options.argv.keystore)); }
|
||||
if (options.argv.keystore)
|
||||
packageArgs.keystore = path.relative(projectRoot, path.resolve(options.argv.keystore));
|
||||
|
||||
['alias','storePassword','password','keystoreType'].forEach(function (flagName) {
|
||||
if (options.argv[flagName]) { packageArgs[flagName] = options.argv[flagName]; }
|
||||
if (options.argv[flagName])
|
||||
packageArgs[flagName] = options.argv[flagName];
|
||||
});
|
||||
|
||||
var buildConfig = options.buildConfig;
|
||||
@ -130,7 +128,8 @@ function parseOpts (options, resolvedTarget, projectRoot) {
|
||||
module.exports.runClean = function(options) {
|
||||
var opts = parseOpts(options, null, this.root);
|
||||
var builder = builders.getBuilder(opts.buildMethod);
|
||||
return builder.prepEnv(opts).then(function () {
|
||||
return builder.prepEnv(opts)
|
||||
.then(function() {
|
||||
return builder.clean(opts);
|
||||
});
|
||||
};
|
||||
@ -149,14 +148,15 @@ module.exports.runClean = function (options) {
|
||||
*/
|
||||
module.exports.run = function(options, optResolvedTarget) {
|
||||
var opts = parseOpts(options, optResolvedTarget, this.root);
|
||||
console.log(opts.buildMethod);
|
||||
var builder = builders.getBuilder(opts.buildMethod);
|
||||
return builder.prepEnv(opts).then(function () {
|
||||
return builder.prepEnv(opts)
|
||||
.then(function() {
|
||||
if (opts.prepEnv) {
|
||||
events.emit('verbose', 'Build file successfully prepared.');
|
||||
return;
|
||||
}
|
||||
return builder.build(opts).then(function () {
|
||||
return builder.build(opts)
|
||||
.then(function() {
|
||||
var apkPaths = builder.findOutputApks(opts.buildType, opts.arch);
|
||||
events.emit('log', 'Built the following apk(s): \n\t' + apkPaths.join('\n\t'));
|
||||
return {
|
||||
@ -174,24 +174,31 @@ module.exports.run = function (options, optResolvedTarget) {
|
||||
*/
|
||||
module.exports.detectArchitecture = function(target) {
|
||||
function helper() {
|
||||
return Adb.shell(target, 'cat /proc/cpuinfo').then(function (output) {
|
||||
return Adb.shell(target, 'cat /proc/cpuinfo')
|
||||
.then(function(output) {
|
||||
return /intel/i.exec(output) ? 'x86' : 'arm';
|
||||
});
|
||||
}
|
||||
// It sometimes happens (at least on OS X), that this command will hang forever.
|
||||
// To fix it, either unplug & replug device, or restart adb server.
|
||||
return helper().timeout(1000, new CordovaError('Device communication timed out. Try unplugging & replugging the device.')).then(null, function (err) {
|
||||
return helper()
|
||||
.timeout(1000, new CordovaError('Device communication timed out. Try unplugging & replugging the device.'))
|
||||
.then(null, function(err) {
|
||||
if (/timed out/.exec('' + err)) {
|
||||
// adb kill-server doesn't seem to do the trick.
|
||||
// Could probably find a x-platform version of killall, but I'm not actually
|
||||
// sure that this scenario even happens on non-OSX machines.
|
||||
events.emit('verbose', 'adb timed out while detecting device/emulator architecture. Killing adb and trying again.');
|
||||
return spawn('killall', ['adb']).then(function () {
|
||||
return helper().then(null, function () {
|
||||
return spawn('killall', ['adb'])
|
||||
.then(function() {
|
||||
return helper()
|
||||
.then(null, function() {
|
||||
// The double kill is sadly often necessary, at least on mac.
|
||||
events.emit('warn', 'adb timed out a second time while detecting device/emulator architecture. Killing adb and trying again.');
|
||||
return spawn('killall', ['adb']).then(function () {
|
||||
return helper().then(null, function () {
|
||||
return spawn('killall', ['adb'])
|
||||
.then(function() {
|
||||
return helper()
|
||||
.then(null, function() {
|
||||
return Q.reject(new CordovaError('adb timed out a third time while detecting device/emulator architecture. Try unplugging & replugging the device.'));
|
||||
});
|
||||
});
|
||||
@ -208,7 +215,7 @@ module.exports.detectArchitecture = function (target) {
|
||||
module.exports.findBestApkForArchitecture = function(buildResults, arch) {
|
||||
var paths = buildResults.apkPaths.filter(function(p) {
|
||||
var apkName = path.basename(p);
|
||||
if (buildResults.buildType === 'debug') {
|
||||
if (buildResults.buildType == 'debug') {
|
||||
return /-debug/.exec(apkName);
|
||||
}
|
||||
return !/-debug/.exec(apkName);
|
||||
|
156
DynamicBibleIonic/platforms/android/cordova/lib/builders/AntBuilder.js
vendored
Normal file
@ -0,0 +1,156 @@
|
||||
/*
|
||||
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 Q = require('q');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var util = require('util');
|
||||
var shell = require('shelljs');
|
||||
var spawn = require('cordova-common').superspawn.spawn;
|
||||
var CordovaError = require('cordova-common').CordovaError;
|
||||
var check_reqs = require('../check_reqs');
|
||||
|
||||
var SIGNING_PROPERTIES = '-signing.properties';
|
||||
var MARKER = 'YOUR CHANGES WILL BE ERASED!';
|
||||
var TEMPLATE =
|
||||
'# This file is automatically generated.\n' +
|
||||
'# Do not modify this file -- ' + MARKER + '\n';
|
||||
|
||||
var GenericBuilder = require('./GenericBuilder');
|
||||
|
||||
function AntBuilder (projectRoot) {
|
||||
GenericBuilder.call(this, projectRoot);
|
||||
|
||||
this.binDirs = {ant: this.binDirs.ant};
|
||||
}
|
||||
|
||||
util.inherits(AntBuilder, GenericBuilder);
|
||||
|
||||
AntBuilder.prototype.getArgs = function(cmd, opts) {
|
||||
var args = [cmd, '-f', path.join(this.root, 'build.xml')];
|
||||
// custom_rules.xml is required for incremental builds.
|
||||
if (hasCustomRules(this.root)) {
|
||||
args.push('-Dout.dir=ant-build', '-Dgen.absolute.dir=ant-gen');
|
||||
}
|
||||
if(opts.packageInfo) {
|
||||
args.push('-propertyfile=' + path.join(this.root, opts.buildType + SIGNING_PROPERTIES));
|
||||
}
|
||||
return args;
|
||||
};
|
||||
|
||||
AntBuilder.prototype.prepEnv = function(opts) {
|
||||
var self = this;
|
||||
return check_reqs.check_ant()
|
||||
.then(function() {
|
||||
// Copy in build.xml on each build so that:
|
||||
// A) we don't require the Android SDK at project creation time, and
|
||||
// B) we always use the SDK's latest version of it.
|
||||
/*jshint -W069 */
|
||||
var sdkDir = process.env['ANDROID_HOME'];
|
||||
/*jshint +W069 */
|
||||
var buildTemplate = fs.readFileSync(path.join(sdkDir, 'tools', 'lib', 'build.template'), 'utf8');
|
||||
function writeBuildXml(projectPath) {
|
||||
var newData = buildTemplate.replace('PROJECT_NAME', self.extractRealProjectNameFromManifest());
|
||||
fs.writeFileSync(path.join(projectPath, 'build.xml'), newData);
|
||||
if (!fs.existsSync(path.join(projectPath, 'local.properties'))) {
|
||||
fs.writeFileSync(path.join(projectPath, 'local.properties'), TEMPLATE);
|
||||
}
|
||||
}
|
||||
writeBuildXml(self.root);
|
||||
var propertiesObj = self.readProjectProperties();
|
||||
var subProjects = propertiesObj.libs;
|
||||
for (var i = 0; i < subProjects.length; ++i) {
|
||||
writeBuildXml(path.join(self.root, subProjects[i]));
|
||||
}
|
||||
if (propertiesObj.systemLibs.length > 0) {
|
||||
throw new CordovaError('Project contains at least one plugin that requires a system library. This is not supported with ANT. Use gradle instead.');
|
||||
}
|
||||
|
||||
var propertiesFile = opts.buildType + SIGNING_PROPERTIES;
|
||||
var propertiesFilePath = path.join(self.root, propertiesFile);
|
||||
if (opts.packageInfo) {
|
||||
fs.writeFileSync(propertiesFilePath, TEMPLATE + opts.packageInfo.toProperties());
|
||||
} else if(isAutoGenerated(propertiesFilePath)) {
|
||||
shell.rm('-f', propertiesFilePath);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Builds the project with ant.
|
||||
* Returns a promise.
|
||||
*/
|
||||
AntBuilder.prototype.build = function(opts) {
|
||||
// Without our custom_rules.xml, we need to clean before building.
|
||||
var ret = Q();
|
||||
if (!hasCustomRules(this.root)) {
|
||||
// clean will call check_ant() for us.
|
||||
ret = this.clean(opts);
|
||||
}
|
||||
|
||||
var args = this.getArgs(opts.buildType == 'debug' ? 'debug' : 'release', opts);
|
||||
return check_reqs.check_ant()
|
||||
.then(function() {
|
||||
return spawn('ant', args, {stdio: 'pipe'});
|
||||
}).progress(function (stdio){
|
||||
if (stdio.stderr) {
|
||||
process.stderr.write(stdio.stderr);
|
||||
} else {
|
||||
process.stdout.write(stdio.stdout);
|
||||
}
|
||||
}).catch(function (error) {
|
||||
if (error.toString().indexOf('Unable to resolve project target') >= 0) {
|
||||
return check_reqs.check_android_target(error).then(function() {
|
||||
// If due to some odd reason - check_android_target succeeds
|
||||
// we should still fail here.
|
||||
return Q.reject(error);
|
||||
});
|
||||
}
|
||||
return Q.reject(error);
|
||||
});
|
||||
};
|
||||
|
||||
AntBuilder.prototype.clean = function(opts) {
|
||||
var args = this.getArgs('clean', opts);
|
||||
var self = this;
|
||||
return check_reqs.check_ant()
|
||||
.then(function() {
|
||||
return spawn('ant', args, {stdio: 'inherit'});
|
||||
})
|
||||
.then(function () {
|
||||
shell.rm('-rf', path.join(self.root, 'out'));
|
||||
|
||||
['debug', 'release'].forEach(function(config) {
|
||||
var propertiesFilePath = path.join(self.root, config + SIGNING_PROPERTIES);
|
||||
if(isAutoGenerated(propertiesFilePath)){
|
||||
shell.rm('-f', propertiesFilePath);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = AntBuilder;
|
||||
|
||||
function hasCustomRules(projectRoot) {
|
||||
return fs.existsSync(path.join(projectRoot, 'custom_rules.xml'));
|
||||
}
|
||||
|
||||
function isAutoGenerated(file) {
|
||||
return fs.existsSync(file) && fs.readFileSync(file, 'utf8').indexOf(MARKER) > 0;
|
||||
}
|
@ -16,23 +16,26 @@
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
/* eslint no-self-assign: 0 */
|
||||
/* eslint no-unused-vars: 0 */
|
||||
|
||||
var Q = require('q');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var shell = require('shelljs');
|
||||
var events = require('cordova-common').events;
|
||||
var CordovaError = require('cordova-common').CordovaError;
|
||||
|
||||
function GenericBuilder (projectDir) {
|
||||
this.root = projectDir || path.resolve(__dirname, '../../..');
|
||||
this.binDirs = {
|
||||
studio: path.join(this.root, 'app', 'build', 'outputs', 'apk'),
|
||||
ant: path.join(this.root, hasCustomRules(this.root) ? 'ant-build' : 'bin'),
|
||||
gradle: path.join(this.root, 'build', 'outputs', 'apk')
|
||||
};
|
||||
}
|
||||
|
||||
function hasCustomRules(projectRoot) {
|
||||
return fs.existsSync(path.join(projectRoot, 'custom_rules.xml'));
|
||||
}
|
||||
|
||||
GenericBuilder.prototype.prepEnv = function() {
|
||||
return Q();
|
||||
};
|
||||
@ -48,23 +51,48 @@ GenericBuilder.prototype.clean = function () {
|
||||
|
||||
GenericBuilder.prototype.findOutputApks = function(build_type, arch) {
|
||||
var self = this;
|
||||
return Object.keys(this.binDirs).reduce(function (result, builderName) {
|
||||
return Object.keys(this.binDirs)
|
||||
.reduce(function (result, builderName) {
|
||||
var binDir = self.binDirs[builderName];
|
||||
return result.concat(findOutputApksHelper(binDir, build_type, builderName === 'ant' ? null : arch));
|
||||
}, []).sort(apkSorter);
|
||||
}, [])
|
||||
.sort(apkSorter);
|
||||
};
|
||||
|
||||
GenericBuilder.prototype.readProjectProperties = function () {
|
||||
function findAllUniq(data, r) {
|
||||
var s = {};
|
||||
var m;
|
||||
while ((m = r.exec(data))) {
|
||||
s[m[1]] = 1;
|
||||
}
|
||||
return Object.keys(s);
|
||||
}
|
||||
|
||||
var data = fs.readFileSync(path.join(this.root, 'project.properties'), 'utf8');
|
||||
return {
|
||||
libs: findAllUniq(data, /^\s*android\.library\.reference\.\d+=(.*)(?:\s|$)/mg),
|
||||
gradleIncludes: findAllUniq(data, /^\s*cordova\.gradle\.include\.\d+=(.*)(?:\s|$)/mg),
|
||||
systemLibs: findAllUniq(data, /^\s*cordova\.system\.library\.\d+=(.*)(?:\s|$)/mg)
|
||||
};
|
||||
};
|
||||
|
||||
GenericBuilder.prototype.extractRealProjectNameFromManifest = function () {
|
||||
var manifestPath = path.join(this.root, 'AndroidManifest.xml');
|
||||
var manifestData = fs.readFileSync(manifestPath, 'utf8');
|
||||
var m = /<manifest[\s\S]*?package\s*=\s*"(.*?)"/i.exec(manifestData);
|
||||
if (!m) {
|
||||
throw new CordovaError('Could not find package name in ' + manifestPath);
|
||||
}
|
||||
|
||||
var packageName=m[1];
|
||||
var lastDotIndex = packageName.lastIndexOf('.');
|
||||
return packageName.substring(lastDotIndex + 1);
|
||||
};
|
||||
|
||||
module.exports = GenericBuilder;
|
||||
|
||||
function apkSorter(fileA, fileB) {
|
||||
// De-prioritize arch specific builds
|
||||
var archSpecificRE = /-x86|-arm/;
|
||||
if (archSpecificRE.exec(fileA)) {
|
||||
return 1;
|
||||
} else if (archSpecificRE.exec(fileB)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// De-prioritize unsigned builds
|
||||
var unsignedRE = /-unsigned/;
|
||||
if (unsignedRE.exec(fileA)) {
|
||||
@ -73,7 +101,7 @@ function apkSorter (fileA, fileB) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
var timeDiff = fs.statSync(fileB).mtime - fs.statSync(fileA).mtime;
|
||||
var timeDiff = fs.statSync(fileA).mtime - fs.statSync(fileB).mtime;
|
||||
return timeDiff === 0 ? fileA.length - fileB.length : timeDiff;
|
||||
}
|
||||
|
||||
@ -81,14 +109,8 @@ function findOutputApksHelper (dir, build_type, arch) {
|
||||
var shellSilent = shell.config.silent;
|
||||
shell.config.silent = true;
|
||||
|
||||
// list directory recursively
|
||||
var ret = shell.ls('-R', dir).map(function (file) {
|
||||
// ls does not include base directory
|
||||
return path.join(dir, file);
|
||||
}).filter(function (file) {
|
||||
// find all APKs
|
||||
return file.match(/\.apk?$/i);
|
||||
}).filter(function (candidate) {
|
||||
var ret = shell.ls(path.join(dir, '*.apk'))
|
||||
.filter(function(candidate) {
|
||||
var apkName = path.basename(candidate);
|
||||
// Need to choose between release and debug .apk.
|
||||
if (build_type === 'debug') {
|
||||
@ -98,7 +120,8 @@ function findOutputApksHelper (dir, build_type, arch) {
|
||||
return /-release/.exec(apkName) && !/-unaligned/.exec(apkName);
|
||||
}
|
||||
return true;
|
||||
}).sort(apkSorter);
|
||||
})
|
||||
.sort(apkSorter);
|
||||
|
||||
shellSilent = shellSilent;
|
||||
|
||||
@ -110,13 +133,13 @@ function findOutputApksHelper (dir, build_type, arch) {
|
||||
// And show only arch-specific ones (or non-arch-specific)
|
||||
ret = ret.filter(function(p) {
|
||||
/*jshint -W018 */
|
||||
return !!/-x86|-arm/.exec(path.basename(p)) === archSpecific;
|
||||
return !!/-x86|-arm/.exec(path.basename(p)) == archSpecific;
|
||||
/*jshint +W018 */
|
||||
});
|
||||
|
||||
if (archSpecific && ret.length > 1 && arch) {
|
||||
ret = ret.filter(function(p) {
|
||||
return path.basename(p).indexOf('-' + arch) !== -1;
|
||||
return path.basename(p).indexOf('-' + arch) != -1;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ var fs = require('fs');
|
||||
var util = require('util');
|
||||
var path = require('path');
|
||||
var shell = require('shelljs');
|
||||
var superspawn = require('cordova-common').superspawn;
|
||||
var spawn = require('cordova-common').superspawn.spawn;
|
||||
var CordovaError = require('cordova-common').CordovaError;
|
||||
var check_reqs = require('../check_reqs');
|
||||
|
||||
@ -43,9 +43,9 @@ function GradleBuilder (projectRoot) {
|
||||
util.inherits(GradleBuilder, GenericBuilder);
|
||||
|
||||
GradleBuilder.prototype.getArgs = function(cmd, opts) {
|
||||
if (cmd === 'release') {
|
||||
if (cmd == 'release') {
|
||||
cmd = 'cdvBuildRelease';
|
||||
} else if (cmd === 'debug') {
|
||||
} else if (cmd == 'debug') {
|
||||
cmd = 'cdvBuildDebug';
|
||||
}
|
||||
var args = [cmd, '-b', path.join(this.root, 'build.gradle')];
|
||||
@ -69,53 +69,16 @@ GradleBuilder.prototype.getArgs = function (cmd, opts) {
|
||||
* This returns a promise
|
||||
*/
|
||||
|
||||
GradleBuilder.prototype.runGradleWrapper = function (gradle_cmd, gradle_file) {
|
||||
GradleBuilder.prototype.runGradleWrapper = function(gradle_cmd) {
|
||||
var gradlePath = path.join(this.root, 'gradlew');
|
||||
gradle_file = path.join(this.root, (gradle_file || 'wrapper.gradle'));
|
||||
var wrapperGradle = path.join(this.root, 'wrapper.gradle');
|
||||
if(fs.existsSync(gradlePath)) {
|
||||
//Literally do nothing, for some reason this works, while !fs.existsSync didn't on Windows
|
||||
} else {
|
||||
return superspawn.spawn(gradle_cmd, ['-p', this.root, 'wrapper', '-b', gradle_file], { stdio: 'pipe' })
|
||||
.progress(function (stdio) {
|
||||
suppressJavaOptionsInfo(stdio);
|
||||
});
|
||||
return spawn(gradle_cmd, ['-p', this.root, 'wrapper', '-b', wrapperGradle], {stdio: 'inherit'});
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* We need to kill this in a fire.
|
||||
*/
|
||||
|
||||
GradleBuilder.prototype.readProjectProperties = function () {
|
||||
function findAllUniq (data, r) {
|
||||
var s = {};
|
||||
var m;
|
||||
while ((m = r.exec(data))) {
|
||||
s[m[1]] = 1;
|
||||
}
|
||||
return Object.keys(s);
|
||||
}
|
||||
|
||||
var data = fs.readFileSync(path.join(this.root, 'project.properties'), 'utf8');
|
||||
return {
|
||||
libs: findAllUniq(data, /^\s*android\.library\.reference\.\d+=(.*)(?:\s|$)/mg),
|
||||
gradleIncludes: findAllUniq(data, /^\s*cordova\.gradle\.include\.\d+=(.*)(?:\s|$)/mg),
|
||||
systemLibs: findAllUniq(data, /^\s*cordova\.system\.library\.\d+=(.*)(?:\s|$)/mg)
|
||||
};
|
||||
};
|
||||
|
||||
GradleBuilder.prototype.extractRealProjectNameFromManifest = function () {
|
||||
var manifestPath = path.join(this.root, 'AndroidManifest.xml');
|
||||
var manifestData = fs.readFileSync(manifestPath, 'utf8');
|
||||
var m = /<manifest[\s\S]*?package\s*=\s*"(.*?)"/i.exec(manifestData);
|
||||
if (!m) {
|
||||
throw new CordovaError('Could not find package name in ' + manifestPath);
|
||||
}
|
||||
|
||||
var packageName = m[1];
|
||||
var lastDotIndex = packageName.lastIndexOf('.');
|
||||
return packageName.substring(lastDotIndex + 1);
|
||||
};
|
||||
|
||||
// Makes the project buildable, minus the gradle wrapper.
|
||||
GradleBuilder.prototype.prepBuildFiles = function() {
|
||||
@ -123,9 +86,6 @@ GradleBuilder.prototype.prepBuildFiles = function () {
|
||||
var pluginBuildGradle = path.join(this.root, 'cordova', 'lib', 'plugin-build.gradle');
|
||||
var propertiesObj = this.readProjectProperties();
|
||||
var subProjects = propertiesObj.libs;
|
||||
|
||||
// Check and copy the gradle file into the subproject.
|
||||
// Called by the loop below this function def.
|
||||
var checkAndCopy = function(subProject, root) {
|
||||
var subProjectGradle = path.join(root, subProject, 'build.gradle');
|
||||
// This is the future-proof way of checking if a file exists
|
||||
@ -136,22 +96,19 @@ GradleBuilder.prototype.prepBuildFiles = function () {
|
||||
shell.cp('-f', pluginBuildGradle, subProjectGradle);
|
||||
}
|
||||
};
|
||||
|
||||
// Some dependencies on Android don't use gradle, or don't have default
|
||||
// gradle files. This copies a dummy gradle file into them
|
||||
for (var i = 0; i < subProjects.length; ++i) {
|
||||
if (subProjects[i] !== 'CordovaLib' && subProjects[i] !== 'app') {
|
||||
if (subProjects[i] !== 'CordovaLib') {
|
||||
checkAndCopy(subProjects[i], this.root);
|
||||
}
|
||||
}
|
||||
|
||||
var name = this.extractRealProjectNameFromManifest();
|
||||
//Remove the proj.id/name- prefix from projects: https://issues.apache.org/jira/browse/CB-9149
|
||||
var settingsGradlePaths = subProjects.map(function(p){
|
||||
var realDir=p.replace(/[/\\]/g, ':');
|
||||
var libName=realDir.replace(name+'-','');
|
||||
var str='include ":'+libName+'"\n';
|
||||
if (realDir.indexOf(name + '-') !== -1) { str += 'project(":' + libName + '").projectDir = new File("' + p + '")\n'; }
|
||||
if(realDir.indexOf(name+'-')!==-1)
|
||||
str+='project(":'+libName+'").projectDir = new File("'+p+'")\n';
|
||||
return str;
|
||||
});
|
||||
|
||||
@ -163,27 +120,24 @@ GradleBuilder.prototype.prepBuildFiles = function () {
|
||||
var buildGradle = fs.readFileSync(path.join(this.root, 'build.gradle'), 'utf8');
|
||||
var depsList = '';
|
||||
var root = this.root;
|
||||
|
||||
// Cordova Plugins can be written as library modules that would use Cordova as a
|
||||
// dependency. Because we need to make sure that Cordova is compiled only once for
|
||||
// dexing, we make sure to exclude CordovaLib from these modules
|
||||
var insertExclude = function(p) {
|
||||
var gradlePath = path.join(root, p, 'build.gradle');
|
||||
var projectGradleFile = fs.readFileSync(gradlePath, 'utf-8');
|
||||
if (projectGradleFile.indexOf('CordovaLib') !== -1) {
|
||||
if(projectGradleFile.indexOf('CordovaLib') != -1) {
|
||||
depsList += '{\n exclude module:("CordovaLib")\n }\n';
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
depsList +='\n';
|
||||
}
|
||||
};
|
||||
|
||||
subProjects.forEach(function(p) {
|
||||
console.log('Subproject Path: ' + p);
|
||||
var libName=p.replace(/[/\\]/g, ':').replace(name+'-','');
|
||||
depsList += ' implementation(project(path: "' + libName + '"))';
|
||||
depsList += ' debugCompile(project(path: "' + libName + '", configuration: "debug"))';
|
||||
insertExclude(p);
|
||||
depsList += ' releaseCompile(project(path: "' + libName + '", configuration: "release"))';
|
||||
insertExclude(p);
|
||||
});
|
||||
|
||||
// For why we do this mapping: https://issues.apache.org/jira/browse/CB-8390
|
||||
var SYSTEM_LIBRARY_MAPPINGS = [
|
||||
[/^\/?extras\/android\/support\/(.*)$/, 'com.android.support:support-$1:+'],
|
||||
@ -208,9 +162,6 @@ GradleBuilder.prototype.prepBuildFiles = function () {
|
||||
}
|
||||
depsList += ' compile "' + mavenRef + '"\n';
|
||||
});
|
||||
|
||||
// This code is dangerous and actually writes gradle declarations directly into the build.gradle
|
||||
// Try not to mess with this if possible
|
||||
buildGradle = buildGradle.replace(/(SUB-PROJECT DEPENDENCIES START)[\s\S]*(\/\/ SUB-PROJECT DEPENDENCIES END)/, '$1\n' + depsList + ' $2');
|
||||
var includeList = '';
|
||||
propertiesObj.gradleIncludes.forEach(function(includePath) {
|
||||
@ -222,7 +173,8 @@ GradleBuilder.prototype.prepBuildFiles = function () {
|
||||
|
||||
GradleBuilder.prototype.prepEnv = function(opts) {
|
||||
var self = this;
|
||||
return check_reqs.check_gradle().then(function (gradlePath) {
|
||||
return check_reqs.check_gradle()
|
||||
.then(function(gradlePath) {
|
||||
return self.runGradleWrapper(gradlePath);
|
||||
}).then(function() {
|
||||
return self.prepBuildFiles();
|
||||
@ -247,7 +199,7 @@ GradleBuilder.prototype.prepEnv = function (opts) {
|
||||
// For some reason, using ^ and $ don't work. This does the job, though.
|
||||
var distributionUrlRegex = /distributionUrl.*zip/;
|
||||
/*jshint -W069 */
|
||||
var distributionUrl = process.env['CORDOVA_ANDROID_GRADLE_DISTRIBUTION_URL'] || 'https\\://services.gradle.org/distributions/gradle-4.1-all.zip';
|
||||
var distributionUrl = process.env['CORDOVA_ANDROID_GRADLE_DISTRIBUTION_URL'] || 'https\\://services.gradle.org/distributions/gradle-3.3-all.zip';
|
||||
/*jshint +W069 */
|
||||
var gradleWrapperPropertiesPath = path.join(self.root, 'gradle', 'wrapper', 'gradle-wrapper.properties');
|
||||
shell.chmod('u+w', gradleWrapperPropertiesPath);
|
||||
@ -269,11 +221,26 @@ GradleBuilder.prototype.prepEnv = function (opts) {
|
||||
*/
|
||||
GradleBuilder.prototype.build = function(opts) {
|
||||
var wrapper = path.join(this.root, 'gradlew');
|
||||
var args = this.getArgs(opts.buildType === 'debug' ? 'debug' : 'release', opts);
|
||||
var args = this.getArgs(opts.buildType == 'debug' ? 'debug' : 'release', opts);
|
||||
|
||||
return superspawn.spawn(wrapper, args, { stdio: 'pipe' })
|
||||
return spawn(wrapper, args, {stdio: 'pipe'})
|
||||
.progress(function (stdio){
|
||||
suppressJavaOptionsInfo(stdio);
|
||||
if (stdio.stderr) {
|
||||
/*
|
||||
* Workaround for the issue with Java printing some unwanted information to
|
||||
* stderr instead of stdout.
|
||||
* This function suppresses 'Picked up _JAVA_OPTIONS' message from being
|
||||
* printed to stderr. See https://issues.apache.org/jira/browse/CB-9971 for
|
||||
* explanation.
|
||||
*/
|
||||
var suppressThisLine = /^Picked up _JAVA_OPTIONS: /i.test(stdio.stderr.toString());
|
||||
if (suppressThisLine) {
|
||||
return;
|
||||
}
|
||||
process.stderr.write(stdio.stderr);
|
||||
} else {
|
||||
process.stdout.write(stdio.stdout);
|
||||
}
|
||||
}).catch(function (error) {
|
||||
if (error.toString().indexOf('failed to find target with hash string') >= 0) {
|
||||
return check_reqs.check_android_target(error).then(function() {
|
||||
@ -291,8 +258,9 @@ GradleBuilder.prototype.clean = function (opts) {
|
||||
var wrapper = path.join(this.root, 'gradlew');
|
||||
var args = builder.getArgs('clean', opts);
|
||||
return Q().then(function() {
|
||||
return superspawn.spawn(wrapper, args, { stdio: 'inherit' });
|
||||
}).then(function () {
|
||||
return spawn(wrapper, args, {stdio: 'inherit'});
|
||||
})
|
||||
.then(function () {
|
||||
shell.rm('-rf', path.join(builder.root, 'out'));
|
||||
|
||||
['debug', 'release'].forEach(function(config) {
|
||||
@ -306,25 +274,6 @@ GradleBuilder.prototype.clean = function (opts) {
|
||||
|
||||
module.exports = GradleBuilder;
|
||||
|
||||
function suppressJavaOptionsInfo (stdio) {
|
||||
if (stdio.stderr) {
|
||||
/*
|
||||
* Workaround for the issue with Java printing some unwanted information to
|
||||
* stderr instead of stdout.
|
||||
* This function suppresses 'Picked up _JAVA_OPTIONS' message from being
|
||||
* printed to stderr. See https://issues.apache.org/jira/browse/CB-9971 for
|
||||
* explanation.
|
||||
*/
|
||||
var suppressThisLine = /^Picked up _JAVA_OPTIONS: /i.test(stdio.stderr.toString());
|
||||
if (suppressThisLine) {
|
||||
return;
|
||||
}
|
||||
process.stderr.write(stdio.stderr);
|
||||
} else {
|
||||
process.stdout.write(stdio.stdout);
|
||||
}
|
||||
}
|
||||
|
||||
function isAutoGenerated(file) {
|
||||
return fs.existsSync(file) && fs.readFileSync(file, 'utf8').indexOf(MARKER) > 0;
|
||||
}
|
||||
|
@ -1,302 +0,0 @@
|
||||
/*
|
||||
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 Q = require('q');
|
||||
var fs = require('fs');
|
||||
var util = require('util');
|
||||
var path = require('path');
|
||||
var shell = require('shelljs');
|
||||
var spawn = require('cordova-common').superspawn.spawn;
|
||||
var CordovaError = require('cordova-common').CordovaError;
|
||||
var check_reqs = require('../check_reqs');
|
||||
|
||||
var GenericBuilder = require('./GenericBuilder');
|
||||
|
||||
var MARKER = 'YOUR CHANGES WILL BE ERASED!';
|
||||
var SIGNING_PROPERTIES = '-signing.properties';
|
||||
var TEMPLATE =
|
||||
'# This file is automatically generated.\n' +
|
||||
'# Do not modify this file -- ' + MARKER + '\n';
|
||||
|
||||
function StudioBuilder (projectRoot) {
|
||||
GenericBuilder.call(this, projectRoot);
|
||||
|
||||
this.binDirs = {gradle: this.binDirs.studio};
|
||||
}
|
||||
|
||||
util.inherits(StudioBuilder, GenericBuilder);
|
||||
|
||||
StudioBuilder.prototype.getArgs = function (cmd, opts) {
|
||||
if (cmd === 'release') {
|
||||
cmd = 'cdvBuildRelease';
|
||||
} else if (cmd === 'debug') {
|
||||
cmd = 'cdvBuildDebug';
|
||||
}
|
||||
var args = [cmd, '-b', path.join(this.root, 'build.gradle')];
|
||||
if (opts.arch) {
|
||||
args.push('-PcdvBuildArch=' + opts.arch);
|
||||
}
|
||||
|
||||
// 10 seconds -> 6 seconds
|
||||
args.push('-Dorg.gradle.daemon=true');
|
||||
// to allow dex in process
|
||||
args.push('-Dorg.gradle.jvmargs=-Xmx2048m');
|
||||
// allow NDK to be used - required by Gradle 1.5 plugin
|
||||
args.push('-Pandroid.useDeprecatedNdk=true');
|
||||
args.push.apply(args, opts.extraArgs);
|
||||
// Shaves another 100ms, but produces a "try at own risk" warning. Not worth it (yet):
|
||||
// args.push('-Dorg.gradle.parallel=true');
|
||||
return args;
|
||||
};
|
||||
|
||||
/*
|
||||
* This returns a promise
|
||||
*/
|
||||
|
||||
StudioBuilder.prototype.runGradleWrapper = function (gradle_cmd) {
|
||||
var gradlePath = path.join(this.root, 'gradlew');
|
||||
var wrapperGradle = path.join(this.root, 'wrapper.gradle');
|
||||
if (fs.existsSync(gradlePath)) {
|
||||
// Literally do nothing, for some reason this works, while !fs.existsSync didn't on Windows
|
||||
} else {
|
||||
return spawn(gradle_cmd, ['-p', this.root, 'wrapper', '-b', wrapperGradle], {stdio: 'inherit'});
|
||||
}
|
||||
};
|
||||
|
||||
StudioBuilder.prototype.readProjectProperties = function () {
|
||||
|
||||
function findAllUniq (data, r) {
|
||||
var s = {};
|
||||
var m;
|
||||
while ((m = r.exec(data))) {
|
||||
s[m[1]] = 1;
|
||||
}
|
||||
return Object.keys(s);
|
||||
}
|
||||
|
||||
var data = fs.readFileSync(path.join(this.root, 'project.properties'), 'utf8');
|
||||
return {
|
||||
libs: findAllUniq(data, /^\s*android\.library\.reference\.\d+=(.*)(?:\s|$)/mg),
|
||||
gradleIncludes: findAllUniq(data, /^\s*cordova\.gradle\.include\.\d+=(.*)(?:\s|$)/mg),
|
||||
systemLibs: findAllUniq(data, /^\s*cordova\.system\.library\.\d+=(.*)(?:\s|$)/mg)
|
||||
};
|
||||
};
|
||||
|
||||
StudioBuilder.prototype.extractRealProjectNameFromManifest = function () {
|
||||
var manifestPath = path.join(this.root, 'app', 'src', 'main', 'AndroidManifest.xml');
|
||||
var manifestData = fs.readFileSync(manifestPath, 'utf8');
|
||||
var m = /<manifest[\s\S]*?package\s*=\s*"(.*?)"/i.exec(manifestData);
|
||||
if (!m) {
|
||||
throw new CordovaError('Could not find package name in ' + manifestPath);
|
||||
}
|
||||
|
||||
var packageName = m[1];
|
||||
var lastDotIndex = packageName.lastIndexOf('.');
|
||||
return packageName.substring(lastDotIndex + 1);
|
||||
};
|
||||
|
||||
// Makes the project buildable, minus the gradle wrapper.
|
||||
StudioBuilder.prototype.prepBuildFiles = function () {
|
||||
// Update the version of build.gradle in each dependent library.
|
||||
var pluginBuildGradle = path.join(this.root, 'cordova', 'lib', 'plugin-build.gradle');
|
||||
var propertiesObj = this.readProjectProperties();
|
||||
var subProjects = propertiesObj.libs;
|
||||
|
||||
// Check and copy the gradle file into the subproject
|
||||
// Called by the loop before this function def
|
||||
|
||||
var checkAndCopy = function (subProject, root) {
|
||||
var subProjectGradle = path.join(root, subProject, 'build.gradle');
|
||||
// This is the future-proof way of checking if a file exists
|
||||
// This must be synchronous to satisfy a Travis test
|
||||
try {
|
||||
fs.accessSync(subProjectGradle, fs.F_OK);
|
||||
} catch (e) {
|
||||
shell.cp('-f', pluginBuildGradle, subProjectGradle);
|
||||
}
|
||||
};
|
||||
|
||||
for (var i = 0; i < subProjects.length; ++i) {
|
||||
if (subProjects[i] !== 'CordovaLib') {
|
||||
checkAndCopy(subProjects[i], this.root);
|
||||
}
|
||||
}
|
||||
var name = this.extractRealProjectNameFromManifest();
|
||||
// Remove the proj.id/name- prefix from projects: https://issues.apache.org/jira/browse/CB-9149
|
||||
var settingsGradlePaths = subProjects.map(function (p) {
|
||||
var realDir = p.replace(/[/\\]/g, ':');
|
||||
var libName = realDir.replace(name + '-', '');
|
||||
var str = 'include ":' + libName + '"\n';
|
||||
if (realDir.indexOf(name + '-') !== -1) {
|
||||
str += 'project(":' + libName + '").projectDir = new File("' + p + '")\n';
|
||||
}
|
||||
return str;
|
||||
});
|
||||
|
||||
fs.writeFileSync(path.join(this.root, 'settings.gradle'),
|
||||
'// GENERATED FILE - DO NOT EDIT\n' +
|
||||
'include ":"\n' + settingsGradlePaths.join(''));
|
||||
|
||||
// Update dependencies within build.gradle.
|
||||
var buildGradle = fs.readFileSync(path.join(this.root, 'app', 'build.gradle'), 'utf8');
|
||||
var depsList = '';
|
||||
var root = this.root;
|
||||
var insertExclude = function (p) {
|
||||
var gradlePath = path.join(root, p, 'build.gradle');
|
||||
var projectGradleFile = fs.readFileSync(gradlePath, 'utf-8');
|
||||
if (projectGradleFile.indexOf('CordovaLib') !== -1) {
|
||||
depsList += '{\n exclude module:("CordovaLib")\n }\n';
|
||||
} else {
|
||||
depsList += '\n';
|
||||
}
|
||||
};
|
||||
subProjects.forEach(function (p) {
|
||||
console.log('Subproject Path: ' + p);
|
||||
var libName = p.replace(/[/\\]/g, ':').replace(name + '-', '');
|
||||
if (libName !== 'app') {
|
||||
depsList += ' implementation(project(path: ":' + libName + '"))';
|
||||
insertExclude(p);
|
||||
}
|
||||
});
|
||||
// For why we do this mapping: https://issues.apache.org/jira/browse/CB-8390
|
||||
var SYSTEM_LIBRARY_MAPPINGS = [
|
||||
[/^\/?extras\/android\/support\/(.*)$/, 'com.android.support:support-$1:+'],
|
||||
[/^\/?google\/google_play_services\/libproject\/google-play-services_lib\/?$/, 'com.google.android.gms:play-services:+']
|
||||
];
|
||||
|
||||
propertiesObj.systemLibs.forEach(function (p) {
|
||||
var mavenRef;
|
||||
// It's already in gradle form if it has two ':'s
|
||||
if (/:.*:/.exec(p)) {
|
||||
mavenRef = p;
|
||||
} else {
|
||||
for (var i = 0; i < SYSTEM_LIBRARY_MAPPINGS.length; ++i) {
|
||||
var pair = SYSTEM_LIBRARY_MAPPINGS[i];
|
||||
if (pair[0].exec(p)) {
|
||||
mavenRef = p.replace(pair[0], pair[1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!mavenRef) {
|
||||
throw new CordovaError('Unsupported system library (does not work with gradle): ' + p);
|
||||
}
|
||||
}
|
||||
depsList += ' compile "' + mavenRef + '"\n';
|
||||
});
|
||||
|
||||
buildGradle = buildGradle.replace(/(SUB-PROJECT DEPENDENCIES START)[\s\S]*(\/\/ SUB-PROJECT DEPENDENCIES END)/, '$1\n' + depsList + ' $2');
|
||||
var includeList = '';
|
||||
|
||||
propertiesObj.gradleIncludes.forEach(function (includePath) {
|
||||
includeList += 'apply from: "../' + includePath + '"\n';
|
||||
});
|
||||
buildGradle = buildGradle.replace(/(PLUGIN GRADLE EXTENSIONS START)[\s\S]*(\/\/ PLUGIN GRADLE EXTENSIONS END)/, '$1\n' + includeList + '$2');
|
||||
// This needs to be stored in the app gradle, not the root grade
|
||||
fs.writeFileSync(path.join(this.root, 'app', 'build.gradle'), buildGradle);
|
||||
};
|
||||
|
||||
StudioBuilder.prototype.prepEnv = function (opts) {
|
||||
var self = this;
|
||||
return check_reqs.check_gradle()
|
||||
.then(function (gradlePath) {
|
||||
return self.runGradleWrapper(gradlePath);
|
||||
}).then(function () {
|
||||
return self.prepBuildFiles();
|
||||
}).then(function () {
|
||||
// If the gradle distribution URL is set, make sure it points to version we want.
|
||||
// If it's not set, do nothing, assuming that we're using a future version of gradle that we don't want to mess with.
|
||||
// For some reason, using ^ and $ don't work. This does the job, though.
|
||||
var distributionUrlRegex = /distributionUrl.*zip/;
|
||||
var distributionUrl = process.env['CORDOVA_ANDROID_GRADLE_DISTRIBUTION_URL'] || 'https\\://services.gradle.org/distributions/gradle-4.1-all.zip';
|
||||
var gradleWrapperPropertiesPath = path.join(self.root, 'gradle', 'wrapper', 'gradle-wrapper.properties');
|
||||
shell.chmod('u+w', gradleWrapperPropertiesPath);
|
||||
shell.sed('-i', distributionUrlRegex, 'distributionUrl=' + distributionUrl, gradleWrapperPropertiesPath);
|
||||
|
||||
var propertiesFile = opts.buildType + SIGNING_PROPERTIES;
|
||||
var propertiesFilePath = path.join(self.root, propertiesFile);
|
||||
if (opts.packageInfo) {
|
||||
fs.writeFileSync(propertiesFilePath, TEMPLATE + opts.packageInfo.toProperties());
|
||||
} else if (isAutoGenerated(propertiesFilePath)) {
|
||||
shell.rm('-f', propertiesFilePath);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Builds the project with gradle.
|
||||
* Returns a promise.
|
||||
*/
|
||||
StudioBuilder.prototype.build = function (opts) {
|
||||
var wrapper = path.join(this.root, 'gradlew');
|
||||
var args = this.getArgs(opts.buildType === 'debug' ? 'debug' : 'release', opts);
|
||||
|
||||
return spawn(wrapper, args, {stdio: 'pipe'})
|
||||
.progress(function (stdio) {
|
||||
if (stdio.stderr) {
|
||||
/*
|
||||
* Workaround for the issue with Java printing some unwanted information to
|
||||
* stderr instead of stdout.
|
||||
* This function suppresses 'Picked up _JAVA_OPTIONS' message from being
|
||||
* printed to stderr. See https://issues.apache.org/jira/browse/CB-9971 for
|
||||
* explanation.
|
||||
*/
|
||||
var suppressThisLine = /^Picked up _JAVA_OPTIONS: /i.test(stdio.stderr.toString());
|
||||
if (suppressThisLine) {
|
||||
return;
|
||||
}
|
||||
process.stderr.write(stdio.stderr);
|
||||
} else {
|
||||
process.stdout.write(stdio.stdout);
|
||||
}
|
||||
}).catch(function (error) {
|
||||
if (error.toString().indexOf('failed to find target with hash string') >= 0) {
|
||||
return check_reqs.check_android_target(error).then(function () {
|
||||
// If due to some odd reason - check_android_target succeeds
|
||||
// we should still fail here.
|
||||
return Q.reject(error);
|
||||
});
|
||||
}
|
||||
return Q.reject(error);
|
||||
});
|
||||
};
|
||||
|
||||
StudioBuilder.prototype.clean = function (opts) {
|
||||
var builder = this;
|
||||
var wrapper = path.join(this.root, 'gradlew');
|
||||
var args = builder.getArgs('clean', opts);
|
||||
return Q().then(function () {
|
||||
return spawn(wrapper, args, {stdio: 'inherit'});
|
||||
})
|
||||
.then(function () {
|
||||
shell.rm('-rf', path.join(builder.root, 'out'));
|
||||
|
||||
['debug', 'release'].forEach(function (config) {
|
||||
var propertiesFilePath = path.join(builder.root, config + SIGNING_PROPERTIES);
|
||||
if (isAutoGenerated(propertiesFilePath)) {
|
||||
shell.rm('-f', propertiesFilePath);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = StudioBuilder;
|
||||
|
||||
function isAutoGenerated (file) {
|
||||
return fs.existsSync(file) && fs.readFileSync(file, 'utf8').indexOf(MARKER) > 0;
|
||||
}
|
@ -20,8 +20,8 @@
|
||||
var CordovaError = require('cordova-common').CordovaError;
|
||||
|
||||
var knownBuilders = {
|
||||
ant: 'AntBuilder',
|
||||
gradle: 'GradleBuilder',
|
||||
studio: 'StudioBuilder',
|
||||
none: 'GenericBuilder'
|
||||
};
|
||||
|
||||
@ -35,7 +35,8 @@ var knownBuilders = {
|
||||
* @return {Builder} A builder instance for specified build type.
|
||||
*/
|
||||
module.exports.getBuilder = function (builderType, projectRoot) {
|
||||
if (!knownBuilders[builderType]) { throw new CordovaError('Builder ' + builderType + ' is not supported.'); }
|
||||
if (!knownBuilders[builderType])
|
||||
throw new CordovaError('Builder ' + builderType + ' is not supported.');
|
||||
|
||||
try {
|
||||
var Builder = require('./' + knownBuilders[builderType]);
|
||||
|
@ -21,14 +21,14 @@
|
||||
|
||||
/* jshint sub:true */
|
||||
|
||||
var shelljs = require('shelljs');
|
||||
var child_process = require('child_process');
|
||||
var Q = require('q');
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var os = require('os');
|
||||
var REPO_ROOT = path.join(__dirname, '..', '..', '..', '..');
|
||||
var PROJECT_ROOT = path.join(__dirname, '..', '..');
|
||||
var shelljs = require('shelljs'),
|
||||
child_process = require('child_process'),
|
||||
Q = require('q'),
|
||||
path = require('path'),
|
||||
fs = require('fs'),
|
||||
os = require('os'),
|
||||
REPO_ROOT = path.join(__dirname, '..', '..', '..', '..'),
|
||||
PROJECT_ROOT = path.join(__dirname, '..', '..');
|
||||
var CordovaError = require('cordova-common').CordovaError;
|
||||
var superspawn = require('cordova-common').superspawn;
|
||||
var android_sdk = require('./android_sdk');
|
||||
@ -53,11 +53,11 @@ function tryCommand (cmd, errMsg, catchStderr) {
|
||||
}
|
||||
|
||||
module.exports.isWindows = function() {
|
||||
return (os.platform() === 'win32');
|
||||
return (os.platform() == 'win32');
|
||||
};
|
||||
|
||||
module.exports.isDarwin = function() {
|
||||
return (os.platform() === 'darwin');
|
||||
return (os.platform() == 'darwin');
|
||||
};
|
||||
|
||||
// Get valid target from framework/project.properties if run from this repo
|
||||
@ -84,13 +84,12 @@ module.exports.get_target = function () {
|
||||
|
||||
// Returns a promise. Called only by build and clean commands.
|
||||
module.exports.check_ant = function() {
|
||||
return superspawn.spawn('ant', ['-version']).then(function (output) {
|
||||
return superspawn.spawn('ant', ['-version'])
|
||||
.then(function(output) {
|
||||
// Parse Ant version from command output
|
||||
return /version ((?:\d+\.)+(?:\d+))/i.exec(output)[1];
|
||||
}).catch(function(err) {
|
||||
if (err) {
|
||||
throw new CordovaError('Failed to run `ant -version`. Make sure you have `ant` on your $PATH.');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@ -99,14 +98,16 @@ module.exports.get_gradle_wrapper = function () {
|
||||
var i = 0;
|
||||
var foundStudio = false;
|
||||
var program_dir;
|
||||
// OK, This hack only works on Windows, not on Mac OS or Linux. We will be deleting this eventually!
|
||||
if (module.exports.isWindows()) {
|
||||
|
||||
var result = child_process.spawnSync(path.join(__dirname, 'getASPath.bat'));
|
||||
// console.log('result.stdout =' + result.stdout.toString());
|
||||
// console.log('result.stderr =' + result.stderr.toString());
|
||||
|
||||
if (result.stderr.toString().length > 0) {
|
||||
if (module.exports.isDarwin()) {
|
||||
program_dir = fs.readdirSync('/Applications');
|
||||
while (i < program_dir.length && !foundStudio) {
|
||||
if (program_dir[i].startsWith('Android Studio')) {
|
||||
//TODO: Check for a specific Android Studio version, make sure it's not Canary
|
||||
androidStudioPath = path.join('/Applications', program_dir[i], 'Contents', 'gradle');
|
||||
foundStudio = true;
|
||||
} else { ++i; }
|
||||
}
|
||||
} else if (module.exports.isWindows()) {
|
||||
var androidPath = path.join(process.env['ProgramFiles'], 'Android') + '/';
|
||||
if (fs.existsSync(androidPath)) {
|
||||
program_dir = fs.readdirSync(androidPath);
|
||||
@ -117,17 +118,11 @@ module.exports.get_gradle_wrapper = function () {
|
||||
} else { ++i; }
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// console.log('got android studio path from registry');
|
||||
// remove the (os independent) new line char at the end of stdout
|
||||
// add gradle to match the above.
|
||||
androidStudioPath = path.join(result.stdout.toString().split('\r\n')[0], 'gradle');
|
||||
}
|
||||
}
|
||||
|
||||
if (androidStudioPath !== null && fs.existsSync(androidStudioPath)) {
|
||||
var dirs = fs.readdirSync(androidStudioPath);
|
||||
if (dirs[0].split('-')[0] === 'gradle') {
|
||||
if(dirs[0].split('-')[0] == 'gradle') {
|
||||
return path.join(androidStudioPath, dirs[0], 'bin', 'gradle');
|
||||
}
|
||||
} else {
|
||||
@ -140,17 +135,17 @@ module.exports.get_gradle_wrapper = function () {
|
||||
module.exports.check_gradle = function() {
|
||||
var sdkDir = process.env['ANDROID_HOME'];
|
||||
var d = Q.defer();
|
||||
if (!sdkDir) {
|
||||
if (!sdkDir)
|
||||
return Q.reject(new CordovaError('Could not find gradle wrapper within Android SDK. Could not find Android SDK directory.\n' +
|
||||
'Might need to install Android SDK or set up \'ANDROID_HOME\' env variable.'));
|
||||
}
|
||||
|
||||
var gradlePath = module.exports.get_gradle_wrapper();
|
||||
if (gradlePath.length !== 0) { d.resolve(gradlePath); } else {
|
||||
if (gradlePath.length !== 0)
|
||||
d.resolve(gradlePath);
|
||||
else
|
||||
d.reject(new CordovaError('Could not find an installed version of Gradle either in Android Studio,\n' +
|
||||
'or on your system to install the gradle wrapper. Please include gradle \n' +
|
||||
'in your path, or install Android Studio'));
|
||||
}
|
||||
return d.promise;
|
||||
};
|
||||
|
||||
@ -168,14 +163,13 @@ module.exports.check_java = function () {
|
||||
if (javacPath) {
|
||||
// OS X has a command for finding JAVA_HOME.
|
||||
var find_java = '/usr/libexec/java_home';
|
||||
var default_java_error_msg = 'Failed to find \'JAVA_HOME\' environment variable. Try setting it manually.';
|
||||
var default_java_error_msg = 'Failed to find \'JAVA_HOME\' environment variable. Try setting setting it manually.';
|
||||
if (fs.existsSync(find_java)) {
|
||||
return superspawn.spawn(find_java).then(function (stdout) {
|
||||
return superspawn.spawn(find_java)
|
||||
.then(function(stdout) {
|
||||
process.env['JAVA_HOME'] = stdout.trim();
|
||||
}).catch(function(err) {
|
||||
if (err) {
|
||||
throw new CordovaError(default_java_error_msg);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// See if we can derive it from javac's location.
|
||||
@ -215,7 +209,8 @@ module.exports.check_java = function () {
|
||||
}
|
||||
// We use tryCommand with catchStderr = true, because
|
||||
// javac writes version info to stderr instead of stdout
|
||||
return tryCommand('javac -version', msg, true).then(function (output) {
|
||||
return tryCommand('javac -version', msg, true)
|
||||
.then(function (output) {
|
||||
//Let's check for at least Java 8, and keep it future proof so we can support Java 10
|
||||
var match = /javac ((?:1\.)(?:[8-9]\.)(?:\d+))|((?:1\.)(?:[1-9]\d+\.)(?:\d+))/i.exec(output);
|
||||
return match && match[1];
|
||||
@ -270,10 +265,10 @@ module.exports.check_android = function () {
|
||||
if (androidCmdPath) {
|
||||
parentDir = path.dirname(androidCmdPath);
|
||||
grandParentDir = path.dirname(parentDir);
|
||||
if (path.basename(parentDir) === 'tools' || fs.existsSync(path.join(grandParentDir, 'tools', 'android'))) {
|
||||
if (path.basename(parentDir) == 'tools' || fs.existsSync(path.join(grandParentDir, 'tools', 'android'))) {
|
||||
maybeSetAndroidHome(grandParentDir);
|
||||
} else {
|
||||
throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting it manually.\n' +
|
||||
throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting setting it manually.\n' +
|
||||
'Detected \'android\' command at ' + parentDir + ' but no \'tools\' directory found near.\n' +
|
||||
'Try reinstall Android SDK or update your PATH to include valid path to SDK' + path.sep + 'tools directory.');
|
||||
}
|
||||
@ -281,10 +276,10 @@ module.exports.check_android = function () {
|
||||
if (adbInPath) {
|
||||
parentDir = path.dirname(adbInPath);
|
||||
grandParentDir = path.dirname(parentDir);
|
||||
if (path.basename(parentDir) === 'platform-tools') {
|
||||
if (path.basename(parentDir) == 'platform-tools') {
|
||||
maybeSetAndroidHome(grandParentDir);
|
||||
} else {
|
||||
throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting it manually.\n' +
|
||||
throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting setting it manually.\n' +
|
||||
'Detected \'adb\' command at ' + parentDir + ' but no \'platform-tools\' directory found near.\n' +
|
||||
'Try reinstall Android SDK or update your PATH to include valid path to SDK' + path.sep + 'platform-tools directory.');
|
||||
}
|
||||
@ -292,17 +287,17 @@ module.exports.check_android = function () {
|
||||
if (avdmanagerInPath) {
|
||||
parentDir = path.dirname(avdmanagerInPath);
|
||||
grandParentDir = path.dirname(parentDir);
|
||||
if (path.basename(parentDir) === 'bin' && path.basename(grandParentDir) === 'tools') {
|
||||
if (path.basename(parentDir) == 'bin' && path.basename(grandParentDir) == 'tools') {
|
||||
maybeSetAndroidHome(path.dirname(grandParentDir));
|
||||
} else {
|
||||
throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting it manually.\n' +
|
||||
throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting setting it manually.\n' +
|
||||
'Detected \'avdmanager\' command at ' + parentDir + ' but no \'tools' + path.sep + 'bin\' directory found near.\n' +
|
||||
'Try reinstall Android SDK or update your PATH to include valid path to SDK' + path.sep + 'tools' + path.sep + 'bin directory.');
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!process.env['ANDROID_HOME']) {
|
||||
throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting it manually.\n' +
|
||||
throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting setting it manually.\n' +
|
||||
'Failed to find \'android\' command in your \'PATH\'. Try update your \'PATH\' to include path to valid SDK directory.');
|
||||
}
|
||||
if (!fs.existsSync(process.env['ANDROID_HOME'])) {
|
||||
@ -342,7 +337,8 @@ module.exports.check_android_target = function (originalError) {
|
||||
// Google Inc.:Google APIs:20
|
||||
// Google Inc.:Glass Development Kit Preview:20
|
||||
var desired_api_level = module.exports.get_target();
|
||||
return android_sdk.list_targets().then(function (targets) {
|
||||
return android_sdk.list_targets()
|
||||
.then(function(targets) {
|
||||
if (targets.indexOf(desired_api_level) >= 0) {
|
||||
return targets;
|
||||
}
|
||||
@ -362,7 +358,8 @@ module.exports.check_android_target = function (originalError) {
|
||||
|
||||
// Returns a promise.
|
||||
module.exports.run = function() {
|
||||
return Q.all([this.check_java(), this.check_android()]).then(function (values) {
|
||||
return Q.all([this.check_java(), this.check_android()])
|
||||
.then(function(values) {
|
||||
console.log('ANDROID_HOME=' + process.env['ANDROID_HOME']);
|
||||
console.log('JAVA_HOME=' + process.env['JAVA_HOME']);
|
||||
|
||||
@ -376,6 +373,7 @@ module.exports.run = function () {
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Object thar represents one of requirements for current platform.
|
||||
* @param {String} id The unique identifier for this requirements.
|
||||
@ -389,7 +387,7 @@ var Requirement = function (id, name, version, installed) {
|
||||
this.name = name;
|
||||
this.installed = installed || false;
|
||||
this.metadata = {
|
||||
version: version
|
||||
version: version,
|
||||
};
|
||||
};
|
||||
|
||||
@ -419,13 +417,15 @@ module.exports.check_all = function () {
|
||||
return checkFns.reduce(function (promise, checkFn, idx) {
|
||||
// Update each requirement with results
|
||||
var requirement = requirements[idx];
|
||||
return promise.then(checkFn).then(function (version) {
|
||||
return promise.then(checkFn)
|
||||
.then(function (version) {
|
||||
requirement.installed = true;
|
||||
requirement.metadata.version = version;
|
||||
}, function (err) {
|
||||
requirement.metadata.reason = err instanceof Error ? err.message : err;
|
||||
});
|
||||
}, Q()).then(function () {
|
||||
}, Q())
|
||||
.then(function () {
|
||||
// When chain is completed, return requirements array to upstream API
|
||||
return requirements;
|
||||
});
|
||||
|
@ -19,8 +19,8 @@
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var Q = require('q');
|
||||
var build = require('./build');
|
||||
var Q = require('q'),
|
||||
build = require('./build');
|
||||
var path = require('path');
|
||||
var Adb = require('./Adb');
|
||||
var AndroidManifest = require('./AndroidManifest');
|
||||
@ -33,12 +33,14 @@ var events = require('cordova-common').events;
|
||||
* @param lookHarder When true, try restarting adb if no devices are found.
|
||||
*/
|
||||
module.exports.list = function(lookHarder) {
|
||||
return Adb.devices().then(function (list) {
|
||||
return Adb.devices()
|
||||
.then(function(list) {
|
||||
if (list.length === 0 && lookHarder) {
|
||||
// adb kill-server doesn't seem to do the trick.
|
||||
// Could probably find a x-platform version of killall, but I'm not actually
|
||||
// sure that this scenario even happens on non-OSX machines.
|
||||
return spawn('killall', ['adb']).then(function () {
|
||||
return spawn('killall', ['adb'])
|
||||
.then(function() {
|
||||
events.emit('verbose', 'Restarting adb to see if more devices are detected.');
|
||||
return Adb.devices();
|
||||
}, function() {
|
||||
@ -51,7 +53,8 @@ module.exports.list = function (lookHarder) {
|
||||
};
|
||||
|
||||
module.exports.resolveTarget = function(target) {
|
||||
return this.list(true).then(function (device_list) {
|
||||
return this.list(true)
|
||||
.then(function(device_list) {
|
||||
if (!device_list || !device_list.length) {
|
||||
return Q.reject(new CordovaError('Failed to deploy to device, no devices found.'));
|
||||
}
|
||||
@ -62,7 +65,8 @@ module.exports.resolveTarget = function (target) {
|
||||
return Q.reject('ERROR: Unable to find target \'' + target + '\'.');
|
||||
}
|
||||
|
||||
return build.detectArchitecture(target).then(function (arch) {
|
||||
return build.detectArchitecture(target)
|
||||
.then(function(arch) {
|
||||
return { target: target, arch: arch, isEmulator: false };
|
||||
});
|
||||
});
|
||||
@ -75,32 +79,36 @@ module.exports.resolveTarget = function (target) {
|
||||
*/
|
||||
module.exports.install = function(target, buildResults) {
|
||||
return Q().then(function() {
|
||||
if (target && typeof target === 'object') {
|
||||
if (target && typeof target == 'object') {
|
||||
return target;
|
||||
}
|
||||
return module.exports.resolveTarget(target);
|
||||
}).then(function(resolvedTarget) {
|
||||
var apk_path = build.findBestApkForArchitecture(buildResults, resolvedTarget.arch);
|
||||
var manifest = new AndroidManifest(path.join(__dirname, '../../app/src/main/AndroidManifest.xml'));
|
||||
var manifest = new AndroidManifest(path.join(__dirname, '../../AndroidManifest.xml'));
|
||||
var pkgName = manifest.getPackageId();
|
||||
var launchName = pkgName + '/.' + manifest.getActivity().getName();
|
||||
events.emit('log', 'Using apk: ' + apk_path);
|
||||
events.emit('log', 'Package name: ' + pkgName);
|
||||
|
||||
return Adb.install(resolvedTarget.target, apk_path, {replace: true}).catch(function (error) {
|
||||
return Adb.install(resolvedTarget.target, apk_path, {replace: true})
|
||||
.catch(function (error) {
|
||||
// CB-9557 CB-10157 only uninstall and reinstall app if the one that
|
||||
// is already installed on device was signed w/different certificate
|
||||
if (!/INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES/.test(error.toString())) { throw error; }
|
||||
if (!/INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES/.test(error.toString()))
|
||||
throw error;
|
||||
|
||||
events.emit('warn', 'Uninstalling app from device and reinstalling it again because the ' +
|
||||
'installed app already signed with different key');
|
||||
|
||||
// This promise is always resolved, even if 'adb uninstall' fails to uninstall app
|
||||
// or the app doesn't installed at all, so no error catching needed.
|
||||
return Adb.uninstall(resolvedTarget.target, pkgName).then(function () {
|
||||
return Adb.uninstall(resolvedTarget.target, pkgName)
|
||||
.then(function() {
|
||||
return Adb.install(resolvedTarget.target, apk_path, {replace: true});
|
||||
});
|
||||
}).then(function () {
|
||||
})
|
||||
.then(function() {
|
||||
//unlock screen
|
||||
return Adb.shell(resolvedTarget.target, 'input keyevent 82');
|
||||
}).then(function() {
|
||||
|
@ -21,7 +21,6 @@
|
||||
|
||||
/* jshint sub:true */
|
||||
|
||||
var android_versions = require('android-versions');
|
||||
var retry = require('./retry');
|
||||
var build = require('./build');
|
||||
var path = require('path');
|
||||
@ -56,7 +55,8 @@ function forgivingWhichSync (cmd) {
|
||||
}
|
||||
|
||||
module.exports.list_images_using_avdmanager = function () {
|
||||
return superspawn.spawn('avdmanager', ['list', 'avd']).then(function (output) {
|
||||
return superspawn.spawn('avdmanager', ['list', 'avd'])
|
||||
.then(function(output) {
|
||||
var response = output.split('\n');
|
||||
var emulator_list = [];
|
||||
for (var i = 1; i < response.length; i++) {
|
||||
@ -116,7 +116,8 @@ module.exports.list_images_using_avdmanager = function () {
|
||||
};
|
||||
|
||||
module.exports.list_images_using_android = function() {
|
||||
return superspawn.spawn('android', ['list', 'avd']).then(function (output) {
|
||||
return superspawn.spawn('android', ['list', 'avd'])
|
||||
.then(function(output) {
|
||||
var response = output.split('\n');
|
||||
var emulator_list = [];
|
||||
for (var i = 1; i < response.length; i++) {
|
||||
@ -170,7 +171,6 @@ module.exports.list_images_using_android = function () {
|
||||
}
|
||||
*/
|
||||
module.exports.list_images = function() {
|
||||
return Q.fcall(function () {
|
||||
if (forgivingWhichSync('avdmanager')) {
|
||||
return module.exports.list_images_using_avdmanager();
|
||||
} else if (forgivingWhichSync('android')) {
|
||||
@ -180,19 +180,6 @@ module.exports.list_images = function () {
|
||||
throw new CordovaError('Could not find either `android` or `avdmanager` on your $PATH! Are you sure the Android SDK is installed and available?');
|
||||
});
|
||||
}
|
||||
}).then(function (avds) {
|
||||
// In case we're missing the Android OS version string from the target description, add it.
|
||||
return avds.map(function (avd) {
|
||||
if (avd.target && avd.target.indexOf('Android API') > -1 && avd.target.indexOf('API level') < 0) {
|
||||
var api_level = avd.target.match(/\d+/);
|
||||
if (api_level) {
|
||||
var level = android_versions.get(api_level);
|
||||
avd.target = 'Android ' + level.semver + ' (API level ' + api_level + ')';
|
||||
}
|
||||
}
|
||||
return avd;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@ -201,18 +188,19 @@ module.exports.list_images = function () {
|
||||
* Returns a promise.
|
||||
*/
|
||||
module.exports.best_image = function() {
|
||||
return this.list_images().then(function (images) {
|
||||
return this.list_images()
|
||||
.then(function(images) {
|
||||
// Just return undefined if there is no images
|
||||
if (images.length === 0) return;
|
||||
|
||||
var closest = 9999;
|
||||
var best = images[0];
|
||||
var project_target = parseInt(check_reqs.get_target().replace('android-', ''));
|
||||
var project_target = check_reqs.get_target().replace('android-', '');
|
||||
for (var i in images) {
|
||||
var target = images[i].target;
|
||||
if (target && target.indexOf('API level') > -1) {
|
||||
var num = parseInt(target.split('(API level ')[1].replace(')', ''));
|
||||
if (num === project_target) {
|
||||
if(target) {
|
||||
var num = target.split('(API level ')[1].replace(')', '');
|
||||
if (num == project_target) {
|
||||
return images[i];
|
||||
} else if (project_target - num < closest && project_target > num) {
|
||||
closest = project_target - num;
|
||||
@ -232,7 +220,8 @@ module.exports.list_started = function () {
|
||||
// Returns a promise.
|
||||
// TODO: we should remove this, there's a more robust method under android_sdk.js
|
||||
module.exports.list_targets = function() {
|
||||
return superspawn.spawn('android', ['list', 'targets'], {cwd: os.tmpdir()}).then(function (output) {
|
||||
return superspawn.spawn('android', ['list', 'targets'], {cwd: os.tmpdir()})
|
||||
.then(function(output) {
|
||||
var target_out = output.split('\n');
|
||||
var targets = [];
|
||||
for (var i = target_out.length; i >= 0; i--) {
|
||||
@ -251,7 +240,8 @@ module.exports.list_targets = function () {
|
||||
module.exports.get_available_port = function () {
|
||||
var self = this;
|
||||
|
||||
return self.list_started().then(function (emulators) {
|
||||
return self.list_started()
|
||||
.then(function (emulators) {
|
||||
for (var p = 5584; p >= 5554; p-=2) {
|
||||
if (emulators.indexOf('emulator-' + p) === -1) {
|
||||
events.emit('verbose', 'Found available port: ' + p);
|
||||
@ -278,7 +268,8 @@ module.exports.start = function (emulator_ID, boot_timeout) {
|
||||
return Q().then(function() {
|
||||
if (emulator_ID) return Q(emulator_ID);
|
||||
|
||||
return self.best_image().then(function (best) {
|
||||
return self.best_image()
|
||||
.then(function(best) {
|
||||
if (best && best.name) {
|
||||
events.emit('warn', 'No emulator specified, defaulting to ' + best.name);
|
||||
return best.name;
|
||||
@ -291,7 +282,8 @@ module.exports.start = function (emulator_ID, boot_timeout) {
|
||||
'HINT: For a faster emulator, use an Intel System Image and install the HAXM device driver\n'));
|
||||
});
|
||||
}).then(function(emulatorId) {
|
||||
return self.get_available_port().then(function (port) {
|
||||
return self.get_available_port()
|
||||
.then(function (port) {
|
||||
// Figure out the directory the emulator binary runs in, and set the cwd to that directory.
|
||||
// Workaround for https://code.google.com/p/android/issues/detail?id=235461
|
||||
var emulator_dir = path.dirname(shelljs.which('emulator'));
|
||||
@ -306,15 +298,18 @@ module.exports.start = function (emulator_ID, boot_timeout) {
|
||||
return self.wait_for_emulator(port);
|
||||
});
|
||||
}).then(function(emulatorId) {
|
||||
if (!emulatorId) { return Q.reject(new CordovaError('Failed to start emulator')); }
|
||||
if (!emulatorId)
|
||||
return Q.reject(new CordovaError('Failed to start emulator'));
|
||||
|
||||
//wait for emulator to boot up
|
||||
process.stdout.write('Waiting for emulator to boot (this may take a while)...');
|
||||
return self.wait_for_boot(emulatorId, boot_timeout).then(function (success) {
|
||||
return self.wait_for_boot(emulatorId, boot_timeout)
|
||||
.then(function(success) {
|
||||
if (success) {
|
||||
events.emit('log','BOOT COMPLETE');
|
||||
//unlock screen
|
||||
return Adb.shell(emulatorId, 'input keyevent 82').then(function () {
|
||||
return Adb.shell(emulatorId, 'input keyevent 82')
|
||||
.then(function() {
|
||||
//return the new emulator id for the started emulators
|
||||
return emulatorId;
|
||||
});
|
||||
@ -334,15 +329,16 @@ module.exports.wait_for_emulator = function (port) {
|
||||
var self = this;
|
||||
return Q().then(function() {
|
||||
var emulator_id = 'emulator-' + port;
|
||||
return Adb.shell(emulator_id, 'getprop dev.bootcomplete').then(function (output) {
|
||||
return Adb.shell(emulator_id, 'getprop dev.bootcomplete')
|
||||
.then(function (output) {
|
||||
if (output.indexOf('1') >= 0) {
|
||||
return emulator_id;
|
||||
}
|
||||
return self.wait_for_emulator(port);
|
||||
}, function (error) {
|
||||
if ((error && error.message &&
|
||||
(error.message.indexOf('not found') > -1)) ||
|
||||
(error.message.indexOf('device offline') > -1)) {
|
||||
if (error && error.message &&
|
||||
(error.message.indexOf('not found') > -1) ||
|
||||
error.message.indexOf('device offline') > -1) {
|
||||
// emulator not yet started, continue waiting
|
||||
return self.wait_for_emulator(port);
|
||||
} else {
|
||||
@ -360,7 +356,8 @@ module.exports.wait_for_emulator = function (port) {
|
||||
*/
|
||||
module.exports.wait_for_boot = function(emulator_id, time_remaining) {
|
||||
var self = this;
|
||||
return Adb.shell(emulator_id, 'ps').then(function (output) {
|
||||
return Adb.shell(emulator_id, 'ps')
|
||||
.then(function(output) {
|
||||
if (output.match(/android\.process\.acore/)) {
|
||||
return true;
|
||||
} else if (time_remaining === 0) {
|
||||
@ -385,7 +382,8 @@ module.exports.wait_for_boot = function (emulator_id, time_remaining) {
|
||||
module.exports.create_image = function(name, target) {
|
||||
console.log('Creating new avd named ' + name);
|
||||
if (target) {
|
||||
return superspawn.spawn('android', ['create', 'avd', '--name', name, '--target', target]).then(null, function (error) {
|
||||
return superspawn.spawn('android', ['create', 'avd', '--name', name, '--target', target])
|
||||
.then(null, function(error) {
|
||||
console.error('ERROR : Failed to create emulator image : ');
|
||||
console.error(' Do you have the latest android targets including ' + target + '?');
|
||||
console.error(error);
|
||||
@ -393,7 +391,8 @@ module.exports.create_image = function (name, target) {
|
||||
} else {
|
||||
console.log('WARNING : Project target not found, creating avd with a different target but the project may fail to install.');
|
||||
// TODO: there's a more robust method for finding targets in android_sdk.js
|
||||
return superspawn.spawn('android', ['create', 'avd', '--name', name, '--target', this.list_targets()[0]]).then(function () {
|
||||
return superspawn.spawn('android', ['create', 'avd', '--name', name, '--target', this.list_targets()[0]])
|
||||
.then(function() {
|
||||
// TODO: This seems like another error case, even though it always happens.
|
||||
console.error('ERROR : Unable to create an avd emulator, no targets found.');
|
||||
console.error('Ensure you have targets available by running the "android" command');
|
||||
@ -406,7 +405,8 @@ module.exports.create_image = function (name, target) {
|
||||
};
|
||||
|
||||
module.exports.resolveTarget = function(target) {
|
||||
return this.list_started().then(function (emulator_list) {
|
||||
return this.list_started()
|
||||
.then(function(emulator_list) {
|
||||
if (emulator_list.length < 1) {
|
||||
return Q.reject('No running Android emulators found, please start an emulator before deploying your project.');
|
||||
}
|
||||
@ -417,7 +417,8 @@ module.exports.resolveTarget = function (target) {
|
||||
return Q.reject('Unable to find target \'' + target + '\'. Failed to deploy to emulator.');
|
||||
}
|
||||
|
||||
return build.detectArchitecture(target).then(function (arch) {
|
||||
return build.detectArchitecture(target)
|
||||
.then(function(arch) {
|
||||
return {target:target, arch:arch, isEmulator:true};
|
||||
});
|
||||
});
|
||||
@ -432,17 +433,12 @@ module.exports.resolveTarget = function (target) {
|
||||
module.exports.install = function(givenTarget, buildResults) {
|
||||
|
||||
var target;
|
||||
// We need to find the proper path to the Android Manifest
|
||||
var manifestPath = path.join(__dirname, '..', '..', 'app', 'src', 'main', 'AndroidManifest.xml');
|
||||
if (buildResults.buildMethod === 'gradle') {
|
||||
manifestPath = path.join(__dirname, '../../AndroidManifest.xml');
|
||||
}
|
||||
var manifest = new AndroidManifest(manifestPath);
|
||||
var manifest = new AndroidManifest(path.join(__dirname, '../../AndroidManifest.xml'));
|
||||
var pkgName = manifest.getPackageId();
|
||||
|
||||
// resolve the target emulator
|
||||
return Q().then(function () {
|
||||
if (givenTarget && typeof givenTarget === 'object') {
|
||||
if (givenTarget && typeof givenTarget == 'object') {
|
||||
return givenTarget;
|
||||
} else {
|
||||
return module.exports.resolveTarget(givenTarget);
|
||||
@ -456,7 +452,8 @@ module.exports.install = function (givenTarget, buildResults) {
|
||||
}).then(function () {
|
||||
// This promise is always resolved, even if 'adb uninstall' fails to uninstall app
|
||||
// or the app doesn't installed at all, so no error catching needed.
|
||||
return Q.when().then(function () {
|
||||
return Q.when()
|
||||
.then(function() {
|
||||
|
||||
var apk_path = build.findBestApkForArchitecture(buildResults, target.arch);
|
||||
var execOptions = {
|
||||
@ -497,23 +494,27 @@ module.exports.install = function (givenTarget, buildResults) {
|
||||
}
|
||||
|
||||
function installPromise () {
|
||||
return adbInstallWithOptions(target.target, apk_path, execOptions).catch(function (error) {
|
||||
return adbInstallWithOptions(target.target, apk_path, execOptions)
|
||||
.catch(function (error) {
|
||||
// CB-9557 CB-10157 only uninstall and reinstall app if the one that
|
||||
// is already installed on device was signed w/different certificate
|
||||
if (!/INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES/.test(error.toString())) { throw error; }
|
||||
if (!/INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES/.test(error.toString()))
|
||||
throw error;
|
||||
|
||||
events.emit('warn', 'Uninstalling app from device and reinstalling it because the ' +
|
||||
'currently installed app was signed with different key');
|
||||
|
||||
// This promise is always resolved, even if 'adb uninstall' fails to uninstall app
|
||||
// or the app doesn't installed at all, so no error catching needed.
|
||||
return Adb.uninstall(target.target, pkgName).then(function () {
|
||||
return Adb.uninstall(target.target, pkgName)
|
||||
.then(function() {
|
||||
return adbInstallWithOptions(target.target, apk_path, execOptions);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return retry.retryPromise(NUM_INSTALL_RETRIES, installPromise).then(function (output) {
|
||||
return retry.retryPromise(NUM_INSTALL_RETRIES, installPromise)
|
||||
.then(function (output) {
|
||||
events.emit('log', 'INSTALL SUCCESS');
|
||||
});
|
||||
});
|
||||
|
@ -1,3 +0,0 @@
|
||||
@ECHO OFF
|
||||
for /f "tokens=2*" %%a in ('REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Android Studio" /v Path') do set "ASPath=%%~b"
|
||||
ECHO %ASPath%
|
@ -18,7 +18,7 @@
|
||||
@ECHO OFF
|
||||
SET script_path="%~dp0install-device"
|
||||
IF EXIST %script_path% (
|
||||
node %script_path% %*
|
||||
node "%script_path%" %*
|
||||
) ELSE (
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'install-device' script in 'cordova\lib' folder, aborting...>&2
|
||||
|
@ -18,7 +18,7 @@
|
||||
@ECHO OFF
|
||||
SET script_path="%~dp0install-emulator"
|
||||
IF EXIST %script_path% (
|
||||
node %script_path% %*
|
||||
node "%script_path%" %*
|
||||
) ELSE (
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'install-emulator' script in 'cordova\lib' folder, aborting...>&2
|
||||
|
@ -18,7 +18,7 @@
|
||||
@ECHO OFF
|
||||
SET script_path="%~dp0list-devices"
|
||||
IF EXIST %script_path% (
|
||||
node %script_path% %*
|
||||
node "%script_path%" %*
|
||||
) ELSE (
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'list-devices' script in 'cordova\lib' folder, aborting...>&2
|
||||
|
@ -18,7 +18,7 @@
|
||||
@ECHO OFF
|
||||
SET script_path="%~dp0list-emulator-images"
|
||||
IF EXIST %script_path% (
|
||||
node %script_path% %*
|
||||
node "%script_path%" %*
|
||||
) ELSE (
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'list-emulator-images' script in 'cordova\lib' folder, aborting...>&2
|
||||
|
@ -18,7 +18,7 @@
|
||||
@ECHO OFF
|
||||
SET script_path="%~dp0list-started-emulators"
|
||||
IF EXIST %script_path% (
|
||||
node %script_path% %*
|
||||
node "%script_path%" %*
|
||||
) ELSE (
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'list-started-emulators' script in 'cordova\lib' folder, aborting...>&2
|
||||
|
@ -19,11 +19,11 @@
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var path = require('path');
|
||||
var os = require('os');
|
||||
var Q = require('q');
|
||||
var child_process = require('child_process');
|
||||
var ROOT = path.join(__dirname, '..', '..');
|
||||
var path = require('path'),
|
||||
os = require('os'),
|
||||
Q = require('q'),
|
||||
child_process = require('child_process'),
|
||||
ROOT = path.join(__dirname, '..', '..');
|
||||
|
||||
/*
|
||||
* Starts running logcat in the shell.
|
||||
|
@ -20,10 +20,8 @@
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
maven {
|
||||
url "https://maven.google.com"
|
||||
}
|
||||
}
|
||||
|
||||
// Switch the Android Gradle plugin version requirement depending on the
|
||||
|
@ -1,4 +1,7 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2013 Anis Kadri
|
||||
*
|
||||
* Licensed 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
|
||||
@ -30,19 +33,8 @@ var handlers = {
|
||||
|
||||
var dest = path.join(obj.targetDir, path.basename(obj.src));
|
||||
|
||||
// TODO: This code needs to be replaced, since the core plugins need to be re-mapped to a different location in
|
||||
// a later plugins release. This is for legacy plugins to work with Cordova.
|
||||
|
||||
if(options && options.android_studio === true) {
|
||||
// If a Java file is using the new directory structure, don't penalize it
|
||||
if (!obj.targetDir.includes('app/src/main')) {
|
||||
if (obj.src.endsWith('.java')) {
|
||||
dest = path.join('app/src/main/java', obj.targetDir.substring(4), path.basename(obj.src));
|
||||
} else if (obj.src.endsWith('.xml')) {
|
||||
// We are making a huge assumption here that XML files will be going to res/xml or values/xml
|
||||
dest = path.join('app/src/main', obj.targetDir, path.basename(obj.src));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (options && options.force) {
|
||||
@ -79,18 +71,10 @@ var handlers = {
|
||||
},
|
||||
'resource-file':{
|
||||
install:function(obj, plugin, project, options) {
|
||||
var dest = path.normalize(obj.target);
|
||||
if (options && options.android_studio === true) {
|
||||
dest = path.join('app/src/main', dest);
|
||||
}
|
||||
copyFile(plugin.dir, obj.src, project.projectDir, dest, !!(options && options.link));
|
||||
copyFile(plugin.dir, obj.src, project.projectDir, path.normalize(obj.target), !!(options && options.link));
|
||||
},
|
||||
uninstall:function(obj, plugin, project, options) {
|
||||
var dest = path.normalize(obj.target);
|
||||
if (options && options.android_studio === true) {
|
||||
dest = path.join('app/src/main', dest);
|
||||
}
|
||||
removeFile(project.projectDir, dest);
|
||||
removeFile(project.projectDir, path.normalize(obj.target));
|
||||
}
|
||||
},
|
||||
'framework': {
|
||||
@ -111,9 +95,9 @@ var handlers = {
|
||||
subDir = src;
|
||||
}
|
||||
|
||||
if (obj.type === 'gradleReference') {
|
||||
if (obj.type == 'gradleReference') {
|
||||
project.addGradleReference(parentDir, subDir);
|
||||
} else if (obj.type === 'sys') {
|
||||
} else if (obj.type == 'sys') {
|
||||
project.addSystemLibrary(parentDir, subDir);
|
||||
} else {
|
||||
project.addSubProject(parentDir, subDir);
|
||||
@ -141,9 +125,9 @@ var handlers = {
|
||||
subDir = src;
|
||||
}
|
||||
|
||||
if (obj.type === 'gradleReference') {
|
||||
if (obj.type == 'gradleReference') {
|
||||
project.removeGradleReference(parentDir, subDir);
|
||||
} else if (obj.type === 'sys') {
|
||||
} else if (obj.type == 'sys') {
|
||||
project.removeSystemLibrary(parentDir, subDir);
|
||||
} else {
|
||||
project.removeSubProject(parentDir, subDir);
|
||||
@ -237,12 +221,14 @@ function copyFile (plugin_dir, src, project_dir, dest, link) {
|
||||
// check that src path is inside plugin directory
|
||||
var real_path = fs.realpathSync(src);
|
||||
var real_plugin_path = fs.realpathSync(plugin_dir);
|
||||
if (real_path.indexOf(real_plugin_path) !== 0) { throw new CordovaError('File "' + src + '" is located outside the plugin directory "' + plugin_dir + '"'); }
|
||||
if (real_path.indexOf(real_plugin_path) !== 0)
|
||||
throw new CordovaError('File "' + src + '" is located outside the plugin directory "' + plugin_dir + '"');
|
||||
|
||||
dest = path.resolve(project_dir, dest);
|
||||
|
||||
// check that dest path is located in project directory
|
||||
if (dest.indexOf(project_dir) !== 0) { throw new CordovaError('Destination "' + dest + '" for source file "' + src + '" is located outside the project'); }
|
||||
if (dest.indexOf(project_dir) !== 0)
|
||||
throw new CordovaError('Destination "' + dest + '" for source file "' + src + '" is located outside the project');
|
||||
|
||||
shell.mkdir('-p', path.dirname(dest));
|
||||
if (link) {
|
||||
@ -258,7 +244,8 @@ function copyFile (plugin_dir, src, project_dir, dest, link) {
|
||||
// Same as copy file but throws error if target exists
|
||||
function copyNewFile (plugin_dir, src, project_dir, dest, link) {
|
||||
var target_path = path.resolve(project_dir, dest);
|
||||
if (fs.existsSync(target_path)) { throw new CordovaError('"' + target_path + '" already exists!'); }
|
||||
if (fs.existsSync(target_path))
|
||||
throw new CordovaError('"' + target_path + '" already exists!');
|
||||
|
||||
copyFile(plugin_dir, src, project_dir, dest, !!link);
|
||||
}
|
||||
@ -273,7 +260,8 @@ function symlinkFileOrDirTree (src, dest) {
|
||||
fs.readdirSync(src).forEach(function(entry) {
|
||||
symlinkFileOrDirTree(path.join(src, entry), path.join(dest, entry));
|
||||
});
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
fs.symlinkSync(path.relative(fs.realpathSync(path.dirname(dest)), src), dest);
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,6 @@
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
/* eslint no-useless-escape: 0 */
|
||||
|
||||
var Q = require('q');
|
||||
var fs = require('fs');
|
||||
@ -24,7 +23,6 @@ var path = require('path');
|
||||
var shell = require('shelljs');
|
||||
var events = require('cordova-common').events;
|
||||
var AndroidManifest = require('./AndroidManifest');
|
||||
var checkReqs = require('./check_reqs');
|
||||
var xmlHelpers = require('cordova-common').xmlHelpers;
|
||||
var CordovaError = require('cordova-common').CordovaError;
|
||||
var ConfigParser = require('cordova-common').ConfigParser;
|
||||
@ -42,14 +40,17 @@ module.exports.prepare = function (cordovaProject, options) {
|
||||
this._config = updateConfigFilesFrom(cordovaProject.projectConfig, munger, this.locations);
|
||||
|
||||
// Update own www dir with project's www assets and plugins' assets and js-files
|
||||
return Q.when(updateWww(cordovaProject, this.locations)).then(function () {
|
||||
return Q.when(updateWww(cordovaProject, this.locations))
|
||||
.then(function () {
|
||||
// update project according to config.xml changes.
|
||||
return updateProjectAccordingTo(self._config, self.locations);
|
||||
}).then(function () {
|
||||
})
|
||||
.then(function () {
|
||||
updateIcons(cordovaProject, path.relative(cordovaProject.root, self.locations.res));
|
||||
updateSplashes(cordovaProject, path.relative(cordovaProject.root, self.locations.res));
|
||||
updateFileResources(cordovaProject, path.relative(cordovaProject.root, self.locations.root));
|
||||
}).then(function () {
|
||||
})
|
||||
.then(function () {
|
||||
events.emit('verbose', 'Prepared android project successfully');
|
||||
});
|
||||
};
|
||||
@ -168,24 +169,17 @@ function cleanWww (projectRoot, locations) {
|
||||
*/
|
||||
function updateProjectAccordingTo(platformConfig, locations) {
|
||||
// Update app name by editing res/values/strings.xml
|
||||
var strings = xmlHelpers.parseElementtreeSync(locations.strings);
|
||||
|
||||
var name = platformConfig.name();
|
||||
var strings = xmlHelpers.parseElementtreeSync(locations.strings);
|
||||
strings.find('string[@name="app_name"]').text = name.replace(/\'/g, '\\\'');
|
||||
|
||||
var shortName = platformConfig.shortName && platformConfig.shortName();
|
||||
if (shortName && shortName !== name) {
|
||||
strings.find('string[@name="launcher_name"]').text = shortName.replace(/\'/g, '\\\'');
|
||||
}
|
||||
|
||||
fs.writeFileSync(locations.strings, strings.write({indent: 4}), 'utf-8');
|
||||
events.emit('verbose', 'Wrote out android application name "' + name + '" to ' + locations.strings);
|
||||
|
||||
// Java packages cannot support dashes
|
||||
var androidPkgName = (platformConfig.android_packageName() || platformConfig.packageName()).replace(/-/g, '_');
|
||||
var pkg = (platformConfig.android_packageName() || platformConfig.packageName()).replace(/-/g, '_');
|
||||
|
||||
var manifest = new AndroidManifest(locations.manifest);
|
||||
var manifestId = manifest.getPackageId();
|
||||
var orig_pkg = manifest.getPackageId();
|
||||
|
||||
manifest.getActivity()
|
||||
.setOrientation(platformConfig.getPreference('orientation'))
|
||||
@ -193,14 +187,13 @@ function updateProjectAccordingTo (platformConfig, locations) {
|
||||
|
||||
manifest.setVersionName(platformConfig.version())
|
||||
.setVersionCode(platformConfig.android_versionCode() || default_versionCode(platformConfig.version()))
|
||||
.setPackageId(androidPkgName)
|
||||
.setPackageId(pkg)
|
||||
.setMinSdkVersion(platformConfig.getPreference('android-minSdkVersion', 'android'))
|
||||
.setMaxSdkVersion(platformConfig.getPreference('android-maxSdkVersion', 'android'))
|
||||
.setTargetSdkVersion(platformConfig.getPreference('android-targetSdkVersion', 'android'))
|
||||
.write();
|
||||
|
||||
// Java file paths shouldn't be hard coded
|
||||
var javaPattern = path.join(locations.javaSrc, manifestId.replace(/\./g, '/'), '*.java');
|
||||
var javaPattern = path.join(locations.root, 'src', orig_pkg.replace(/\./g, '/'), '*.java');
|
||||
var java_files = shell.ls(javaPattern).filter(function(f) {
|
||||
return shell.grep(/extends\s+CordovaActivity/g, f);
|
||||
});
|
||||
@ -211,16 +204,12 @@ function updateProjectAccordingTo (platformConfig, locations) {
|
||||
events.emit('log', 'Multiple candidate Java files that extend CordovaActivity found. Guessing at the first one, ' + java_files[0]);
|
||||
}
|
||||
|
||||
var destFile = path.join(locations.root, 'app', 'src', 'main', 'java', androidPkgName.replace(/\./g, '/'), path.basename(java_files[0]));
|
||||
var destFile = path.join(locations.root, 'src', pkg.replace(/\./g, '/'), path.basename(java_files[0]));
|
||||
shell.mkdir('-p', path.dirname(destFile));
|
||||
shell.sed(/package [\w\.]*;/, 'package ' + androidPkgName + ';', java_files[0]).to(destFile);
|
||||
events.emit('verbose', 'Wrote out Android package name "' + androidPkgName + '" to ' + destFile);
|
||||
shell.sed(/package [\w\.]*;/, 'package ' + pkg + ';', java_files[0]).to(destFile);
|
||||
events.emit('verbose', 'Wrote out Android package name "' + pkg + '" to ' + destFile);
|
||||
|
||||
var removeOrigPkg = checkReqs.isWindows() || checkReqs.isDarwin() ?
|
||||
manifestId.toUpperCase() !== androidPkgName.toUpperCase() :
|
||||
manifestId !== androidPkgName;
|
||||
|
||||
if (removeOrigPkg) {
|
||||
if (orig_pkg !== pkg) {
|
||||
// If package was name changed we need to remove old java with main activity
|
||||
shell.rm('-Rf',java_files[0]);
|
||||
// remove any empty directories
|
||||
@ -281,7 +270,7 @@ function updateSplashes (cordovaProject, platformResourcesDir) {
|
||||
if (!resource.density) {
|
||||
return;
|
||||
}
|
||||
if (resource.density === 'mdpi') {
|
||||
if (resource.density == 'mdpi') {
|
||||
hadMdpi = true;
|
||||
}
|
||||
var targetPath = getImageResourcePath(
|
||||
@ -406,13 +395,15 @@ function cleanIcons (projectRoot, projectConfig, platformResourcesDir) {
|
||||
*/
|
||||
function mapImageResources(rootDir, subDir, type, resourceName) {
|
||||
var pathMap = {};
|
||||
shell.ls(path.join(rootDir, subDir, type + '-*')).forEach(function (drawableFolder) {
|
||||
shell.ls(path.join(rootDir, subDir, type + '-*'))
|
||||
.forEach(function (drawableFolder) {
|
||||
var imagePath = path.join(subDir, path.basename(drawableFolder), resourceName);
|
||||
pathMap[imagePath] = null;
|
||||
});
|
||||
return pathMap;
|
||||
}
|
||||
|
||||
|
||||
function updateFileResources(cordovaProject, platformDir) {
|
||||
var files = cordovaProject.projectConfig.getFileResources('android');
|
||||
|
||||
@ -433,8 +424,9 @@ function updateFileResources (cordovaProject, platformDir) {
|
||||
resourceMap, { rootDir: cordovaProject.root }, logFileOp);
|
||||
}
|
||||
|
||||
|
||||
function cleanFileResources(projectRoot, projectConfig, platformDir) {
|
||||
var files = projectConfig.getFileResources('android', true);
|
||||
var files = projectConfig.getFileResources('android');
|
||||
if (files.length > 0) {
|
||||
events.emit('verbose', 'Cleaning resource files at ' + platformDir);
|
||||
|
||||
@ -445,8 +437,7 @@ function cleanFileResources (projectRoot, projectConfig, platformDir) {
|
||||
});
|
||||
|
||||
FileUpdater.updatePaths(
|
||||
resourceMap, {
|
||||
rootDir: projectRoot, all: true}, logFileOp);
|
||||
resourceMap, { rootDir: projectRoot, all: true}, logFileOp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,12 +21,12 @@
|
||||
|
||||
/* jshint loopfunc:true */
|
||||
|
||||
var path = require('path');
|
||||
var build = require('./build');
|
||||
var emulator = require('./emulator');
|
||||
var device = require('./device');
|
||||
var Q = require('q');
|
||||
var events = require('cordova-common').events;
|
||||
var path = require('path'),
|
||||
build = require('./build'),
|
||||
emulator = require('./emulator'),
|
||||
device = require('./device'),
|
||||
Q = require('q'),
|
||||
events = require('cordova-common').events;
|
||||
|
||||
function getInstallTarget(runOptions) {
|
||||
var install_target;
|
||||
@ -56,10 +56,12 @@ module.exports.run = function (runOptions) {
|
||||
var self = this;
|
||||
var install_target = getInstallTarget(runOptions);
|
||||
|
||||
return Q().then(function () {
|
||||
return Q()
|
||||
.then(function() {
|
||||
if (!install_target) {
|
||||
// no target given, deploy to device if available, otherwise use the emulator.
|
||||
return device.list().then(function (device_list) {
|
||||
return device.list()
|
||||
.then(function(device_list) {
|
||||
if (device_list.length > 0) {
|
||||
events.emit('warn', 'No target specified, deploying to device \'' + device_list[0] + '\'.');
|
||||
install_target = device_list[0];
|
||||
@ -70,30 +72,35 @@ module.exports.run = function (runOptions) {
|
||||
});
|
||||
}
|
||||
}).then(function() {
|
||||
if (install_target === '--device') {
|
||||
if (install_target == '--device') {
|
||||
return device.resolveTarget(null);
|
||||
} else if (install_target === '--emulator') {
|
||||
} else if (install_target == '--emulator') {
|
||||
// Give preference to any already started emulators. Else, start one.
|
||||
return emulator.list_started().then(function (started) {
|
||||
return emulator.list_started()
|
||||
.then(function(started) {
|
||||
return started && started.length > 0 ? started[0] : emulator.start();
|
||||
}).then(function(emulatorId) {
|
||||
return emulator.resolveTarget(emulatorId);
|
||||
});
|
||||
}
|
||||
// They specified a specific device/emulator ID.
|
||||
return device.list().then(function (devices) {
|
||||
return device.list()
|
||||
.then(function(devices) {
|
||||
if (devices.indexOf(install_target) > -1) {
|
||||
return device.resolveTarget(install_target);
|
||||
}
|
||||
return emulator.list_started().then(function (started_emulators) {
|
||||
return emulator.list_started()
|
||||
.then(function(started_emulators) {
|
||||
if (started_emulators.indexOf(install_target) > -1) {
|
||||
return emulator.resolveTarget(install_target);
|
||||
}
|
||||
return emulator.list_images().then(function (avds) {
|
||||
return emulator.list_images()
|
||||
.then(function(avds) {
|
||||
// if target emulator isn't started, then start it.
|
||||
for (var avd in avds) {
|
||||
if (avds[avd].name === install_target) {
|
||||
return emulator.start(install_target).then(function (emulatorId) {
|
||||
if (avds[avd].name == install_target) {
|
||||
return emulator.start(install_target)
|
||||
.then(function(emulatorId) {
|
||||
return emulator.resolveTarget(emulatorId);
|
||||
});
|
||||
}
|
||||
@ -107,9 +114,11 @@ module.exports.run = function (runOptions) {
|
||||
// build results (according to platformApi spec) so they are in different
|
||||
// format than emulator.install expects.
|
||||
// TODO: Update emulator/device.install to handle this change
|
||||
return build.run.call(self, runOptions, resolvedTarget).then(function (buildResults) {
|
||||
return build.run.call(self, runOptions, resolvedTarget)
|
||||
.then(function(buildResults) {
|
||||
if (resolvedTarget.isEmulator) {
|
||||
return emulator.wait_for_boot(resolvedTarget.target).then(function () {
|
||||
return emulator.wait_for_boot(resolvedTarget.target)
|
||||
.then(function () {
|
||||
return emulator.install(resolvedTarget, buildResults);
|
||||
});
|
||||
}
|
||||
|
@ -18,7 +18,7 @@
|
||||
@ECHO OFF
|
||||
SET script_path="%~dp0start-emulator"
|
||||
IF EXIST %script_path% (
|
||||
node %script_path% %*
|
||||
node "%script_path%" %*
|
||||
) ELSE (
|
||||
ECHO.
|
||||
ECHO ERROR: Could not find 'start-emulator' script in 'cordova\lib' folder, aborting...>&2
|
||||
|
@ -20,7 +20,7 @@
|
||||
*/
|
||||
|
||||
// Coho updates this line:
|
||||
var VERSION = "7.0.0";
|
||||
var VERSION = "6.2.3";
|
||||
|
||||
module.exports.version = VERSION;
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
#Fri Jan 05 03:48:26 EST 2018
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
|
||||
|
22
DynamicBibleIonic/platforms/android/gradlew
vendored
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
#!/usr/bin/env sh
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
@ -154,11 +154,19 @@ if $cygwin ; then
|
||||
esac
|
||||
fi
|
||||
|
||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
||||
function splitJvmOpts() {
|
||||
JVM_OPTS=("$@")
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
||||
APP_ARGS=$(save "$@")
|
||||
|
||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
|
@ -49,7 +49,6 @@ goto fail
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
if "%@eval[2+2]" == "4" goto 4NT_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
@ -60,11 +59,6 @@ set _SKIP=2
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
goto execute
|
||||
|
||||
:4NT_args
|
||||
@rem Get arguments from the 4NT Shell from JP Software
|
||||
set CMD_LINE_ARGS=%$
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Platform: android
|
||||
// 4450a4cea50616e080a82e8ede9e3d6a1fe3c3ec
|
||||
// 7ef9f9c03167a4dde4372d869472241b6816fee9
|
||||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
@ -19,29 +19,31 @@
|
||||
under the License.
|
||||
*/
|
||||
;(function() {
|
||||
var PLATFORM_VERSION_BUILD_LABEL = '7.0.0';
|
||||
var PLATFORM_VERSION_BUILD_LABEL = '6.2.3';
|
||||
// file: src/scripts/require.js
|
||||
|
||||
/*jshint -W079 */
|
||||
/*jshint -W020 */
|
||||
|
||||
var require;
|
||||
var define;
|
||||
var require,
|
||||
define;
|
||||
|
||||
(function () {
|
||||
var modules = {};
|
||||
var modules = {},
|
||||
// Stack of moduleIds currently being built.
|
||||
var requireStack = [];
|
||||
requireStack = [],
|
||||
// Map of module ID -> index into requireStack of modules currently being built.
|
||||
var inProgressModules = {};
|
||||
var SEPARATOR = '.';
|
||||
inProgressModules = {},
|
||||
SEPARATOR = ".";
|
||||
|
||||
|
||||
|
||||
function build(module) {
|
||||
var factory = module.factory;
|
||||
var localRequire = function (id) {
|
||||
var factory = module.factory,
|
||||
localRequire = function (id) {
|
||||
var resultantId = id;
|
||||
//Its a relative path, so lop off the last portion and add the id (minus "./")
|
||||
if (id.charAt(0) === '.') {
|
||||
if (id.charAt(0) === ".") {
|
||||
resultantId = module.id.slice(0, module.id.lastIndexOf(SEPARATOR)) + SEPARATOR + id.slice(2);
|
||||
}
|
||||
return require(resultantId);
|
||||
@ -54,10 +56,10 @@ var define;
|
||||
|
||||
require = function (id) {
|
||||
if (!modules[id]) {
|
||||
throw 'module ' + id + ' not found';
|
||||
throw "module " + id + " not found";
|
||||
} else if (id in inProgressModules) {
|
||||
var cycle = requireStack.slice(inProgressModules[id]).join('->') + '->' + id;
|
||||
throw 'Cycle in require graph: ' + cycle;
|
||||
throw "Cycle in require graph: " + cycle;
|
||||
}
|
||||
if (modules[id].factory) {
|
||||
try {
|
||||
@ -74,7 +76,7 @@ var define;
|
||||
|
||||
define = function (id, factory) {
|
||||
if (modules[id]) {
|
||||
throw 'module ' + id + ' already defined';
|
||||
throw "module " + id + " already defined";
|
||||
}
|
||||
|
||||
modules[id] = {
|
||||
@ -91,7 +93,7 @@ var define;
|
||||
})();
|
||||
|
||||
//Export for use in node
|
||||
if (typeof module === 'object' && typeof require === 'function') {
|
||||
if (typeof module === "object" && typeof require === "function") {
|
||||
module.exports.require = require;
|
||||
module.exports.define = define;
|
||||
}
|
||||
@ -101,13 +103,15 @@ define("cordova", function(require, exports, module) {
|
||||
|
||||
// Workaround for Windows 10 in hosted environment case
|
||||
// http://www.w3.org/html/wg/drafts/html/master/browsers.html#named-access-on-the-window-object
|
||||
if (window.cordova && !(window.cordova instanceof HTMLElement)) { // eslint-disable-line no-undef
|
||||
throw new Error('cordova already defined');
|
||||
if (window.cordova && !(window.cordova instanceof HTMLElement)) {
|
||||
throw new Error("cordova already defined");
|
||||
}
|
||||
|
||||
|
||||
var channel = require('cordova/channel');
|
||||
var platform = require('cordova/platform');
|
||||
|
||||
|
||||
/**
|
||||
* Intercept calls to addEventListener + removeEventListener and handle deviceready,
|
||||
* resume, and pause events.
|
||||
@ -120,12 +124,12 @@ var m_window_removeEventListener = window.removeEventListener;
|
||||
/**
|
||||
* Houses custom event handlers to intercept on document + window event listeners.
|
||||
*/
|
||||
var documentEventHandlers = {};
|
||||
var windowEventHandlers = {};
|
||||
var documentEventHandlers = {},
|
||||
windowEventHandlers = {};
|
||||
|
||||
document.addEventListener = function(evt, handler, capture) {
|
||||
var e = evt.toLowerCase();
|
||||
if (typeof documentEventHandlers[e] !== 'undefined') {
|
||||
if (typeof documentEventHandlers[e] != 'undefined') {
|
||||
documentEventHandlers[e].subscribe(handler);
|
||||
} else {
|
||||
m_document_addEventListener.call(document, evt, handler, capture);
|
||||
@ -134,7 +138,7 @@ document.addEventListener = function (evt, handler, capture) {
|
||||
|
||||
window.addEventListener = function(evt, handler, capture) {
|
||||
var e = evt.toLowerCase();
|
||||
if (typeof windowEventHandlers[e] !== 'undefined') {
|
||||
if (typeof windowEventHandlers[e] != 'undefined') {
|
||||
windowEventHandlers[e].subscribe(handler);
|
||||
} else {
|
||||
m_window_addEventListener.call(window, evt, handler, capture);
|
||||
@ -144,7 +148,7 @@ window.addEventListener = function (evt, handler, capture) {
|
||||
document.removeEventListener = function(evt, handler, capture) {
|
||||
var e = evt.toLowerCase();
|
||||
// If unsubscribing from an event that is handled by a plugin
|
||||
if (typeof documentEventHandlers[e] !== 'undefined') {
|
||||
if (typeof documentEventHandlers[e] != "undefined") {
|
||||
documentEventHandlers[e].unsubscribe(handler);
|
||||
} else {
|
||||
m_document_removeEventListener.call(document, evt, handler, capture);
|
||||
@ -154,7 +158,7 @@ document.removeEventListener = function (evt, handler, capture) {
|
||||
window.removeEventListener = function(evt, handler, capture) {
|
||||
var e = evt.toLowerCase();
|
||||
// If unsubscribing from an event that is handled by a plugin
|
||||
if (typeof windowEventHandlers[e] !== 'undefined') {
|
||||
if (typeof windowEventHandlers[e] != "undefined") {
|
||||
windowEventHandlers[e].unsubscribe(handler);
|
||||
} else {
|
||||
m_window_removeEventListener.call(window, evt, handler, capture);
|
||||
@ -174,16 +178,13 @@ function createEvent (type, data) {
|
||||
return event;
|
||||
}
|
||||
|
||||
/* eslint-disable no-undef */
|
||||
|
||||
var cordova = {
|
||||
define:define,
|
||||
require:require,
|
||||
version:PLATFORM_VERSION_BUILD_LABEL,
|
||||
platformVersion:PLATFORM_VERSION_BUILD_LABEL,
|
||||
platformId:platform.id,
|
||||
|
||||
/* eslint-enable no-undef */
|
||||
|
||||
/**
|
||||
* Methods to add/remove your own addEventListener hijacking on document + window.
|
||||
*/
|
||||
@ -217,13 +218,14 @@ var cordova = {
|
||||
*/
|
||||
fireDocumentEvent: function(type, data, bNoDetach) {
|
||||
var evt = createEvent(type, data);
|
||||
if (typeof documentEventHandlers[type] !== 'undefined') {
|
||||
if (typeof documentEventHandlers[type] != 'undefined') {
|
||||
if( bNoDetach ) {
|
||||
documentEventHandlers[type].fire(evt);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
setTimeout(function() {
|
||||
// Fire deviceready on listeners that were registered before cordova.js was loaded.
|
||||
if (type === 'deviceready') {
|
||||
if (type == 'deviceready') {
|
||||
document.dispatchEvent(evt);
|
||||
}
|
||||
documentEventHandlers[type].fire(evt);
|
||||
@ -235,7 +237,7 @@ var cordova = {
|
||||
},
|
||||
fireWindowEvent: function(type, data) {
|
||||
var evt = createEvent(type,data);
|
||||
if (typeof windowEventHandlers[type] !== 'undefined') {
|
||||
if (typeof windowEventHandlers[type] != 'undefined') {
|
||||
setTimeout(function() {
|
||||
windowEventHandlers[type].fire(evt);
|
||||
}, 0);
|
||||
@ -287,7 +289,7 @@ var cordova = {
|
||||
try {
|
||||
var callback = cordova.callbacks[callbackId];
|
||||
if (callback) {
|
||||
if (isSuccess && status === cordova.callbackStatus.OK) {
|
||||
if (isSuccess && status == cordova.callbackStatus.OK) {
|
||||
callback.success && callback.success.apply(null, args);
|
||||
} else if (!isSuccess) {
|
||||
callback.fail && callback.fail.apply(null, args);
|
||||
@ -304,10 +306,11 @@ var cordova = {
|
||||
delete cordova.callbacks[callbackId];
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
var msg = 'Error in ' + (isSuccess ? 'Success' : 'Error') + ' callbackId: ' + callbackId + ' : ' + err;
|
||||
}
|
||||
catch (err) {
|
||||
var msg = "Error in " + (isSuccess ? "Success" : "Error") + " callbackId: " + callbackId + " : " + err;
|
||||
console && console.log && console.log(msg);
|
||||
cordova.fireWindowEvent('cordovacallbackerror', { 'message': msg });
|
||||
cordova.fireWindowEvent("cordovacallbackerror", { 'message': msg });
|
||||
throw err;
|
||||
}
|
||||
},
|
||||
@ -316,17 +319,18 @@ var cordova = {
|
||||
try {
|
||||
func();
|
||||
} catch(e) {
|
||||
console.log('Failed to run constructor: ' + e);
|
||||
console.log("Failed to run constructor: " + e);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
module.exports = cordova;
|
||||
|
||||
});
|
||||
|
||||
// file: /Users/jbowser/cordova/cordova-android/cordova-js-src/android/nativeapiprovider.js
|
||||
// file: /Users/maj/src/cordova-android/cordova-js-src/android/nativeapiprovider.js
|
||||
define("cordova/android/nativeapiprovider", function(require, exports, module) {
|
||||
|
||||
/**
|
||||
@ -349,7 +353,7 @@ module.exports = {
|
||||
|
||||
});
|
||||
|
||||
// file: /Users/jbowser/cordova/cordova-android/cordova-js-src/android/promptbasednativeapi.js
|
||||
// file: /Users/maj/src/cordova-android/cordova-js-src/android/promptbasednativeapi.js
|
||||
define("cordova/android/promptbasednativeapi", function(require, exports, module) {
|
||||
|
||||
/**
|
||||
@ -398,18 +402,18 @@ function checkArgs (spec, functionName, args, opt_callee) {
|
||||
var errMsg = null;
|
||||
var typeName;
|
||||
for (var i = 0; i < spec.length; ++i) {
|
||||
var c = spec.charAt(i);
|
||||
var cUpper = c.toUpperCase();
|
||||
var arg = args[i];
|
||||
var c = spec.charAt(i),
|
||||
cUpper = c.toUpperCase(),
|
||||
arg = args[i];
|
||||
// Asterix means allow anything.
|
||||
if (c === '*') {
|
||||
if (c == '*') {
|
||||
continue;
|
||||
}
|
||||
typeName = utils.typeName(arg);
|
||||
if ((arg === null || arg === undefined) && c === cUpper) {
|
||||
if ((arg === null || arg === undefined) && c == cUpper) {
|
||||
continue;
|
||||
}
|
||||
if (typeName !== typeMap[cUpper]) {
|
||||
if (typeName != typeMap[cUpper]) {
|
||||
errMsg = 'Expected ' + typeMap[cUpper];
|
||||
break;
|
||||
}
|
||||
@ -418,7 +422,7 @@ function checkArgs (spec, functionName, args, opt_callee) {
|
||||
errMsg += ', but got ' + typeName + '.';
|
||||
errMsg = 'Wrong type for parameter "' + extractParamName(opt_callee || args.callee, i) + '" of ' + functionName + ': ' + errMsg;
|
||||
// Don't log when running unit tests.
|
||||
if (typeof jasmine === 'undefined') {
|
||||
if (typeof jasmine == 'undefined') {
|
||||
console.error(errMsg);
|
||||
}
|
||||
throw TypeError(errMsg);
|
||||
@ -433,6 +437,7 @@ moduleExports.checkArgs = checkArgs;
|
||||
moduleExports.getValue = getValue;
|
||||
moduleExports.enableChecks = true;
|
||||
|
||||
|
||||
});
|
||||
|
||||
// file: src/common/base64.js
|
||||
@ -446,7 +451,7 @@ base64.fromArrayBuffer = function (arrayBuffer) {
|
||||
};
|
||||
|
||||
base64.toArrayBuffer = function(str) {
|
||||
var decodedStr = typeof atob !== 'undefined' ? atob(str) : Buffer.from(str, 'base64').toString('binary'); // eslint-disable-line no-undef
|
||||
var decodedStr = typeof atob != 'undefined' ? atob(str) : new Buffer(str,'base64').toString('binary');
|
||||
var arrayBuffer = new ArrayBuffer(decodedStr.length);
|
||||
var array = new Uint8Array(arrayBuffer);
|
||||
for (var i=0, len=decodedStr.length; i < len; i++) {
|
||||
@ -462,7 +467,7 @@ base64.toArrayBuffer = function (str) {
|
||||
* platforms tested.
|
||||
*/
|
||||
|
||||
var b64_6bit = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
||||
var b64_6bit = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
var b64_12bit;
|
||||
|
||||
var b64_12bitTable = function() {
|
||||
@ -478,7 +483,7 @@ var b64_12bitTable = function () {
|
||||
|
||||
function uint8ToBase64(rawData) {
|
||||
var numBytes = rawData.byteLength;
|
||||
var output = '';
|
||||
var output="";
|
||||
var segment;
|
||||
var table = b64_12bitTable();
|
||||
for (var i=0;i<numBytes-2;i+=3) {
|
||||
@ -486,12 +491,12 @@ function uint8ToBase64 (rawData) {
|
||||
output += table[segment >> 12];
|
||||
output += table[segment & 0xfff];
|
||||
}
|
||||
if (numBytes - i === 2) {
|
||||
if (numBytes - i == 2) {
|
||||
segment = (rawData[i] << 16) + (rawData[i+1] << 8);
|
||||
output += table[segment >> 12];
|
||||
output += b64_6bit[(segment & 0xfff) >> 6];
|
||||
output += '=';
|
||||
} else if (numBytes - i === 1) {
|
||||
} else if (numBytes - i == 1) {
|
||||
segment = (rawData[i] << 16);
|
||||
output += table[segment >> 12];
|
||||
output += '==';
|
||||
@ -563,7 +568,7 @@ function include (parent, objects, clobber, merge) {
|
||||
result = parent[key];
|
||||
} else {
|
||||
// Overwrite if not currently defined.
|
||||
if (typeof parent[key] === 'undefined') {
|
||||
if (typeof parent[key] == 'undefined') {
|
||||
assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
|
||||
} else {
|
||||
// Set result to what already exists, so we can build children into it if they exist.
|
||||
@ -622,8 +627,8 @@ exports.replaceHookForTesting = function () {};
|
||||
// file: src/common/channel.js
|
||||
define("cordova/channel", function(require, exports, module) {
|
||||
|
||||
var utils = require('cordova/utils');
|
||||
var nextGuid = 1;
|
||||
var utils = require('cordova/utils'),
|
||||
nextGuid = 1;
|
||||
|
||||
/**
|
||||
* Custom pub-sub "channel" that can have functions subscribed to it
|
||||
@ -676,16 +681,16 @@ var Channel = function (type, sticky) {
|
||||
// Function that is called when the first listener is subscribed, or when
|
||||
// the last listener is unsubscribed.
|
||||
this.onHasSubscribersChange = null;
|
||||
};
|
||||
var channel = {
|
||||
},
|
||||
channel = {
|
||||
/**
|
||||
* Calls the provided function only after all of the channels specified
|
||||
* have been fired. All channels must be sticky channels.
|
||||
*/
|
||||
join: function(h, c) {
|
||||
var len = c.length;
|
||||
var i = len;
|
||||
var f = function () {
|
||||
var len = c.length,
|
||||
i = len,
|
||||
f = function() {
|
||||
if (!(--i)) h();
|
||||
};
|
||||
for (var j=0; j<len; j++) {
|
||||
@ -696,14 +701,13 @@ var channel = {
|
||||
}
|
||||
if (!len) h();
|
||||
},
|
||||
/* eslint-disable no-return-assign */
|
||||
create: function(type) {
|
||||
return channel[type] = new Channel(type, false);
|
||||
},
|
||||
createSticky: function(type) {
|
||||
return channel[type] = new Channel(type, true);
|
||||
},
|
||||
/* eslint-enable no-return-assign */
|
||||
|
||||
/**
|
||||
* cordova Channels that must fire before "deviceready" is fired.
|
||||
*/
|
||||
@ -739,10 +743,10 @@ var channel = {
|
||||
};
|
||||
|
||||
function checkSubscriptionArgument(argument) {
|
||||
if (typeof argument !== 'function' && typeof argument.handleEvent !== 'function') {
|
||||
if (typeof argument !== "function" && typeof argument.handleEvent !== "function") {
|
||||
throw new Error(
|
||||
'Must provide a function or an EventListener object ' +
|
||||
'implementing the handleEvent interface.'
|
||||
"Must provide a function or an EventListener object " +
|
||||
"implementing the handleEvent interface."
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -758,7 +762,7 @@ Channel.prototype.subscribe = function (eventListenerOrFunction, eventListener)
|
||||
checkSubscriptionArgument(eventListenerOrFunction);
|
||||
var handleEvent, guid;
|
||||
|
||||
if (eventListenerOrFunction && typeof eventListenerOrFunction === 'object') {
|
||||
if (eventListenerOrFunction && typeof eventListenerOrFunction === "object") {
|
||||
// Received an EventListener object implementing the handleEvent interface
|
||||
handleEvent = eventListenerOrFunction.handleEvent;
|
||||
eventListener = eventListenerOrFunction;
|
||||
@ -767,13 +771,13 @@ Channel.prototype.subscribe = function (eventListenerOrFunction, eventListener)
|
||||
handleEvent = eventListenerOrFunction;
|
||||
}
|
||||
|
||||
if (this.state === 2) {
|
||||
if (this.state == 2) {
|
||||
handleEvent.apply(eventListener || this, this.fireArgs);
|
||||
return;
|
||||
}
|
||||
|
||||
guid = eventListenerOrFunction.observer_guid;
|
||||
if (typeof eventListener === 'object') {
|
||||
if (typeof eventListener === "object") {
|
||||
handleEvent = utils.close(eventListener, handleEvent);
|
||||
}
|
||||
|
||||
@ -788,7 +792,7 @@ Channel.prototype.subscribe = function (eventListenerOrFunction, eventListener)
|
||||
if (!this.handlers[guid]) {
|
||||
this.handlers[guid] = handleEvent;
|
||||
this.numHandlers++;
|
||||
if (this.numHandlers === 1) {
|
||||
if (this.numHandlers == 1) {
|
||||
this.onHasSubscribersChange && this.onHasSubscribersChange();
|
||||
}
|
||||
}
|
||||
@ -801,7 +805,7 @@ Channel.prototype.unsubscribe = function (eventListenerOrFunction) {
|
||||
checkSubscriptionArgument(eventListenerOrFunction);
|
||||
var handleEvent, guid, handler;
|
||||
|
||||
if (eventListenerOrFunction && typeof eventListenerOrFunction === 'object') {
|
||||
if (eventListenerOrFunction && typeof eventListenerOrFunction === "object") {
|
||||
// Received an EventListener object implementing the handleEvent interface
|
||||
handleEvent = eventListenerOrFunction.handleEvent;
|
||||
} else {
|
||||
@ -824,10 +828,10 @@ Channel.prototype.unsubscribe = function (eventListenerOrFunction) {
|
||||
* Calls all functions subscribed to this channel.
|
||||
*/
|
||||
Channel.prototype.fire = function(e) {
|
||||
var fail = false; // eslint-disable-line no-unused-vars
|
||||
var fireArgs = Array.prototype.slice.call(arguments);
|
||||
var fail = false,
|
||||
fireArgs = Array.prototype.slice.call(arguments);
|
||||
// Apply stickiness.
|
||||
if (this.state === 1) {
|
||||
if (this.state == 1) {
|
||||
this.state = 2;
|
||||
this.fireArgs = fireArgs;
|
||||
}
|
||||
@ -841,7 +845,7 @@ Channel.prototype.fire = function (e) {
|
||||
for (var i = 0; i < toCall.length; ++i) {
|
||||
toCall[i].apply(this, fireArgs);
|
||||
}
|
||||
if (this.state === 2 && this.numHandlers) {
|
||||
if (this.state == 2 && this.numHandlers) {
|
||||
this.numHandlers = 0;
|
||||
this.handlers = {};
|
||||
this.onHasSubscribersChange && this.onHasSubscribersChange();
|
||||
@ -849,6 +853,7 @@ Channel.prototype.fire = function (e) {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// defining them here so they are ready super fast!
|
||||
// DOM event that is received when the web page is loaded and parsed.
|
||||
channel.createSticky('onDOMContentLoaded');
|
||||
@ -881,7 +886,7 @@ module.exports = channel;
|
||||
|
||||
});
|
||||
|
||||
// file: /Users/jbowser/cordova/cordova-android/cordova-js-src/exec.js
|
||||
// file: /Users/maj/src/cordova-android/cordova-js-src/exec.js
|
||||
define("cordova/exec", function(require, exports, module) {
|
||||
|
||||
/**
|
||||
@ -1166,6 +1171,7 @@ module.exports = androidExec;
|
||||
// file: src/common/exec/proxy.js
|
||||
define("cordova/exec/proxy", function(require, exports, module) {
|
||||
|
||||
|
||||
// internal map of proxy function
|
||||
var CommandProxyMap = {};
|
||||
|
||||
@ -1173,7 +1179,7 @@ module.exports = {
|
||||
|
||||
// example: cordova.commandProxy.add("Accelerometer",{getCurrentAcceleration: function(successCallback, errorCallback, options) {...},...);
|
||||
add:function(id,proxyObj) {
|
||||
console.log('adding proxy for ' + id);
|
||||
console.log("adding proxy for " + id);
|
||||
CommandProxyMap[id] = proxyObj;
|
||||
return proxyObj;
|
||||
},
|
||||
@ -1190,7 +1196,6 @@ module.exports = {
|
||||
return ( CommandProxyMap[service] ? CommandProxyMap[service][action] : null );
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
// file: src/common/init.js
|
||||
@ -1207,14 +1212,14 @@ var platformInitChannelsArray = [channel.onNativeReady, channel.onPluginsReady];
|
||||
|
||||
function logUnfiredChannels(arr) {
|
||||
for (var i = 0; i < arr.length; ++i) {
|
||||
if (arr[i].state !== 2) {
|
||||
if (arr[i].state != 2) {
|
||||
console.log('Channel not fired: ' + arr[i].type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.setTimeout(function() {
|
||||
if (channel.onDeviceReady.state !== 2) {
|
||||
if (channel.onDeviceReady.state != 2) {
|
||||
console.log('deviceready has not fired after 5 seconds.');
|
||||
logUnfiredChannels(platformInitChannelsArray);
|
||||
logUnfiredChannels(channel.deviceReadyChannelsArray);
|
||||
@ -1231,9 +1236,10 @@ function replaceNavigator (origNavigator) {
|
||||
// Without it, APIs such as getGamepads() break.
|
||||
if (CordovaNavigator.bind) {
|
||||
for (var key in origNavigator) {
|
||||
if (typeof origNavigator[key] === 'function') {
|
||||
if (typeof origNavigator[key] == 'function') {
|
||||
newNavigator[key] = origNavigator[key].bind(origNavigator);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
(function(k) {
|
||||
utils.defineGetterSetter(newNavigator,key,function() {
|
||||
return origNavigator[k];
|
||||
@ -1256,7 +1262,7 @@ if (!window.console) {
|
||||
}
|
||||
if (!window.console.warn) {
|
||||
window.console.warn = function(msg) {
|
||||
this.log('warn: ' + msg);
|
||||
this.log("warn: " + msg);
|
||||
};
|
||||
}
|
||||
|
||||
@ -1267,7 +1273,7 @@ channel.onActivated = cordova.addDocumentEventHandler('activated');
|
||||
channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
|
||||
|
||||
// Listen for DOMContentLoaded and notify our channel subscribers.
|
||||
if (document.readyState === 'complete' || document.readyState === 'interactive') {
|
||||
if (document.readyState == 'complete' || document.readyState == 'interactive') {
|
||||
channel.onDOMContentLoaded.fire();
|
||||
} else {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
@ -1317,6 +1323,7 @@ channel.join(function () {
|
||||
|
||||
}, platformInitChannelsArray);
|
||||
|
||||
|
||||
});
|
||||
|
||||
// file: src/common/init_b.js
|
||||
@ -1336,14 +1343,14 @@ cordova.exec = require('cordova/exec');
|
||||
|
||||
function logUnfiredChannels(arr) {
|
||||
for (var i = 0; i < arr.length; ++i) {
|
||||
if (arr[i].state !== 2) {
|
||||
if (arr[i].state != 2) {
|
||||
console.log('Channel not fired: ' + arr[i].type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.setTimeout(function() {
|
||||
if (channel.onDeviceReady.state !== 2) {
|
||||
if (channel.onDeviceReady.state != 2) {
|
||||
console.log('deviceready has not fired after 5 seconds.');
|
||||
logUnfiredChannels(platformInitChannelsArray);
|
||||
logUnfiredChannels(channel.deviceReadyChannelsArray);
|
||||
@ -1360,9 +1367,10 @@ function replaceNavigator (origNavigator) {
|
||||
// Without it, APIs such as getGamepads() break.
|
||||
if (CordovaNavigator.bind) {
|
||||
for (var key in origNavigator) {
|
||||
if (typeof origNavigator[key] === 'function') {
|
||||
if (typeof origNavigator[key] == 'function') {
|
||||
newNavigator[key] = origNavigator[key].bind(origNavigator);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
(function(k) {
|
||||
utils.defineGetterSetter(newNavigator,key,function() {
|
||||
return origNavigator[k];
|
||||
@ -1384,7 +1392,7 @@ if (!window.console) {
|
||||
}
|
||||
if (!window.console.warn) {
|
||||
window.console.warn = function(msg) {
|
||||
this.log('warn: ' + msg);
|
||||
this.log("warn: " + msg);
|
||||
};
|
||||
}
|
||||
|
||||
@ -1395,7 +1403,7 @@ channel.onActivated = cordova.addDocumentEventHandler('activated');
|
||||
channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
|
||||
|
||||
// Listen for DOMContentLoaded and notify our channel subscribers.
|
||||
if (document.readyState === 'complete' || document.readyState === 'interactive') {
|
||||
if (document.readyState == 'complete' || document.readyState == 'interactive') {
|
||||
channel.onDOMContentLoaded.fire();
|
||||
} else {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
@ -1446,10 +1454,10 @@ channel.join(function () {
|
||||
// file: src/common/modulemapper.js
|
||||
define("cordova/modulemapper", function(require, exports, module) {
|
||||
|
||||
var builder = require('cordova/builder');
|
||||
var moduleMap = define.moduleMap; // eslint-disable-line no-undef
|
||||
var symbolList;
|
||||
var deprecationMap;
|
||||
var builder = require('cordova/builder'),
|
||||
moduleMap = define.moduleMap,
|
||||
symbolList,
|
||||
deprecationMap;
|
||||
|
||||
exports.reset = function() {
|
||||
symbolList = [];
|
||||
@ -1489,7 +1497,7 @@ function prepareNamespace (symbolPath, context) {
|
||||
}
|
||||
var parts = symbolPath.split('.');
|
||||
var cur = context;
|
||||
for (var i = 0, part; part = parts[i]; ++i) { // eslint-disable-line no-cond-assign
|
||||
for (var i = 0, part; part = parts[i]; ++i) {
|
||||
cur = cur[part] = cur[part] || {};
|
||||
}
|
||||
return cur;
|
||||
@ -1503,7 +1511,7 @@ exports.mapModules = function (context) {
|
||||
var moduleName = symbolList[i + 1];
|
||||
var module = require(moduleName);
|
||||
// <runs/>
|
||||
if (strategy === 'r') {
|
||||
if (strategy == 'r') {
|
||||
continue;
|
||||
}
|
||||
var symbolPath = symbolList[i + 2];
|
||||
@ -1515,9 +1523,9 @@ exports.mapModules = function (context) {
|
||||
var parentObj = prepareNamespace(namespace, context);
|
||||
var target = parentObj[lastName];
|
||||
|
||||
if (strategy === 'm' && target) {
|
||||
if (strategy == 'm' && target) {
|
||||
builder.recursiveMerge(target, module);
|
||||
} else if ((strategy === 'd' && !target) || (strategy !== 'd')) {
|
||||
} else if ((strategy == 'd' && !target) || (strategy != 'd')) {
|
||||
if (!(symbolPath in origSymbols)) {
|
||||
origSymbols[symbolPath] = target;
|
||||
}
|
||||
@ -1541,14 +1549,15 @@ exports.getOriginalSymbol = function (context, symbolPath) {
|
||||
|
||||
exports.reset();
|
||||
|
||||
|
||||
});
|
||||
|
||||
// file: src/common/modulemapper_b.js
|
||||
define("cordova/modulemapper_b", function(require, exports, module) {
|
||||
|
||||
var builder = require('cordova/builder');
|
||||
var symbolList = [];
|
||||
var deprecationMap;
|
||||
var builder = require('cordova/builder'),
|
||||
symbolList = [],
|
||||
deprecationMap;
|
||||
|
||||
exports.reset = function() {
|
||||
symbolList = [];
|
||||
@ -1585,7 +1594,7 @@ function prepareNamespace (symbolPath, context) {
|
||||
}
|
||||
var parts = symbolPath.split('.');
|
||||
var cur = context;
|
||||
for (var i = 0, part; part = parts[i]; ++i) { // eslint-disable-line no-cond-assign
|
||||
for (var i = 0, part; part = parts[i]; ++i) {
|
||||
cur = cur[part] = cur[part] || {};
|
||||
}
|
||||
return cur;
|
||||
@ -1599,7 +1608,7 @@ exports.mapModules = function (context) {
|
||||
var moduleName = symbolList[i + 1];
|
||||
var module = require(moduleName);
|
||||
// <runs/>
|
||||
if (strategy === 'r') {
|
||||
if (strategy == 'r') {
|
||||
continue;
|
||||
}
|
||||
var symbolPath = symbolList[i + 2];
|
||||
@ -1611,9 +1620,9 @@ exports.mapModules = function (context) {
|
||||
var parentObj = prepareNamespace(namespace, context);
|
||||
var target = parentObj[lastName];
|
||||
|
||||
if (strategy === 'm' && target) {
|
||||
if (strategy == 'm' && target) {
|
||||
builder.recursiveMerge(target, module);
|
||||
} else if ((strategy === 'd' && !target) || (strategy !== 'd')) {
|
||||
} else if ((strategy == 'd' && !target) || (strategy != 'd')) {
|
||||
if (!(symbolPath in origSymbols)) {
|
||||
origSymbols[symbolPath] = target;
|
||||
}
|
||||
@ -1637,9 +1646,10 @@ exports.getOriginalSymbol = function (context, symbolPath) {
|
||||
|
||||
exports.reset();
|
||||
|
||||
|
||||
});
|
||||
|
||||
// file: /Users/jbowser/cordova/cordova-android/cordova-js-src/platform.js
|
||||
// file: /Users/maj/src/cordova-android/cordova-js-src/platform.js
|
||||
define("cordova/platform", function(require, exports, module) {
|
||||
|
||||
// The last resume event that was received that had the result of a plugin call.
|
||||
@ -1749,7 +1759,7 @@ function onMessageFromNative(msg) {
|
||||
|
||||
});
|
||||
|
||||
// file: /Users/jbowser/cordova/cordova-android/cordova-js-src/plugin/android/app.js
|
||||
// file: /Users/maj/src/cordova-android/cordova-js-src/plugin/android/app.js
|
||||
define("cordova/plugin/android/app", function(require, exports, module) {
|
||||
|
||||
var exec = require('cordova/exec');
|
||||
@ -1846,11 +1856,12 @@ module.exports = {
|
||||
define("cordova/pluginloader", function(require, exports, module) {
|
||||
|
||||
var modulemapper = require('cordova/modulemapper');
|
||||
var urlutil = require('cordova/urlutil');
|
||||
|
||||
// Helper function to inject a <script> tag.
|
||||
// Exported for testing.
|
||||
exports.injectScript = function(url, onload, onerror) {
|
||||
var script = document.createElement('script');
|
||||
var script = document.createElement("script");
|
||||
// onload fires even when script fails loads with an error.
|
||||
script.onload = onload;
|
||||
// onerror fires for malformed URLs.
|
||||
@ -1861,11 +1872,11 @@ exports.injectScript = function (url, onload, onerror) {
|
||||
|
||||
function injectIfNecessary(id, url, onload, onerror) {
|
||||
onerror = onerror || onload;
|
||||
if (id in define.moduleMap) { // eslint-disable-line no-undef
|
||||
if (id in define.moduleMap) {
|
||||
onload();
|
||||
} else {
|
||||
exports.injectScript(url, function() {
|
||||
if (id in define.moduleMap) { // eslint-disable-line no-undef
|
||||
if (id in define.moduleMap) {
|
||||
onload();
|
||||
} else {
|
||||
onerror();
|
||||
@ -1876,7 +1887,7 @@ function injectIfNecessary (id, url, onload, onerror) {
|
||||
|
||||
function onScriptLoadingComplete(moduleList, finishPluginLoading) {
|
||||
// Loop through all the plugins and then through their clobbers and merges.
|
||||
for (var i = 0, module; module = moduleList[i]; i++) { // eslint-disable-line no-cond-assign
|
||||
for (var i = 0, module; module = moduleList[i]; i++) {
|
||||
if (module.clobbers && module.clobbers.length) {
|
||||
for (var j = 0; j < module.clobbers.length; j++) {
|
||||
modulemapper.clobbers(module.id, module.clobbers[j]);
|
||||
@ -1927,7 +1938,7 @@ function findCordovaPath () {
|
||||
var term = '/cordova.js';
|
||||
for (var n = scripts.length-1; n>-1; n--) {
|
||||
var src = scripts[n].src.replace(/\?.*$/, ''); // Strip any query param (CB-6007).
|
||||
if (src.indexOf(term) === (src.length - term.length)) {
|
||||
if (src.indexOf(term) == (src.length - term.length)) {
|
||||
path = src.substring(0, src.length - term.length) + '/';
|
||||
break;
|
||||
}
|
||||
@ -1945,11 +1956,12 @@ exports.load = function (callback) {
|
||||
pathPrefix = '';
|
||||
}
|
||||
injectIfNecessary('cordova/plugin_list', pathPrefix + 'cordova_plugins.js', function() {
|
||||
var moduleList = require('cordova/plugin_list');
|
||||
var moduleList = require("cordova/plugin_list");
|
||||
handlePluginsObject(pathPrefix, moduleList, callback);
|
||||
}, callback);
|
||||
};
|
||||
|
||||
|
||||
});
|
||||
|
||||
// file: src/common/pluginloader_b.js
|
||||
@ -1966,7 +1978,7 @@ function handlePluginsObject (moduleList) {
|
||||
}
|
||||
|
||||
// Loop through all the modules and then through their clobbers and merges.
|
||||
for (var i = 0, module; module = moduleList[i]; i++) { // eslint-disable-line no-cond-assign
|
||||
for (var i = 0, module; module = moduleList[i]; i++) {
|
||||
if (module.clobbers && module.clobbers.length) {
|
||||
for (var j = 0; j < module.clobbers.length; j++) {
|
||||
modulemapper.clobbers(module.id, module.clobbers[j]);
|
||||
@ -1991,17 +2003,19 @@ function handlePluginsObject (moduleList) {
|
||||
// onDeviceReady is blocked on onPluginsReady. onPluginsReady is fired when there are
|
||||
// no plugins to load, or they are all done.
|
||||
exports.load = function(callback) {
|
||||
var moduleList = require('cordova/plugin_list');
|
||||
var moduleList = require("cordova/plugin_list");
|
||||
handlePluginsObject(moduleList);
|
||||
|
||||
callback();
|
||||
};
|
||||
|
||||
|
||||
});
|
||||
|
||||
// file: src/common/urlutil.js
|
||||
define("cordova/urlutil", function(require, exports, module) {
|
||||
|
||||
|
||||
/**
|
||||
* For already absolute URLs, returns what is passed in.
|
||||
* For relative URLs, converts them to absolute ones.
|
||||
@ -2012,6 +2026,7 @@ exports.makeAbsolute = function makeAbsolute (url) {
|
||||
return anchorEl.href;
|
||||
};
|
||||
|
||||
|
||||
});
|
||||
|
||||
// file: src/common/utils.js
|
||||
@ -2051,7 +2066,7 @@ utils.arrayIndexOf = function (a, item) {
|
||||
}
|
||||
var len = a.length;
|
||||
for (var i = 0; i < len; ++i) {
|
||||
if (a[i] === item) {
|
||||
if (a[i] == item) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
@ -2063,10 +2078,10 @@ utils.arrayIndexOf = function (a, item) {
|
||||
*/
|
||||
utils.arrayRemove = function(a, item) {
|
||||
var index = utils.arrayIndexOf(a, item);
|
||||
if (index !== -1) {
|
||||
if (index != -1) {
|
||||
a.splice(index, 1);
|
||||
}
|
||||
return index !== -1;
|
||||
return index != -1;
|
||||
};
|
||||
|
||||
utils.typeName = function(val) {
|
||||
@ -2077,7 +2092,7 @@ utils.typeName = function (val) {
|
||||
* Returns an indication of whether the argument is an array or not
|
||||
*/
|
||||
utils.isArray = Array.isArray ||
|
||||
function (a) { return utils.typeName(a) === 'Array'; };
|
||||
function(a) {return utils.typeName(a) == 'Array';};
|
||||
|
||||
/**
|
||||
* Returns an indication of whether the argument is a Date or not
|
||||
@ -2090,7 +2105,7 @@ utils.isDate = function (d) {
|
||||
* Does a deep clone of the object.
|
||||
*/
|
||||
utils.clone = function(obj) {
|
||||
if (!obj || typeof obj === 'function' || utils.isDate(obj) || typeof obj !== 'object') {
|
||||
if(!obj || typeof obj == 'function' || utils.isDate(obj) || typeof obj != 'object') {
|
||||
return obj;
|
||||
}
|
||||
|
||||
@ -2109,7 +2124,7 @@ utils.clone = function (obj) {
|
||||
// https://issues.apache.org/jira/browse/CB-11522 'unknown' type may be returned in
|
||||
// custom protocol activation case on Windows Phone 8.1 causing "No such interface supported" exception
|
||||
// on cloning.
|
||||
if ((!(i in retVal) || retVal[i] !== obj[i]) && typeof obj[i] !== 'undefined' && typeof obj[i] !== 'unknown') { // eslint-disable-line valid-typeof
|
||||
if((!(i in retVal) || retVal[i] != obj[i]) && typeof obj[i] != 'undefined' && typeof obj[i] != 'unknown') {
|
||||
retVal[i] = utils.clone(obj[i]);
|
||||
}
|
||||
}
|
||||
@ -2128,11 +2143,11 @@ utils.close = function (context, func, params) {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
function UUIDcreatePart(length) {
|
||||
var uuidpart = '';
|
||||
var uuidpart = "";
|
||||
for (var i=0; i<length; i++) {
|
||||
var uuidchar = parseInt((Math.random() * 256), 10).toString(16);
|
||||
if (uuidchar.length === 1) {
|
||||
uuidchar = '0' + uuidchar;
|
||||
if (uuidchar.length == 1) {
|
||||
uuidchar = "0" + uuidchar;
|
||||
}
|
||||
uuidpart += uuidchar;
|
||||
}
|
||||
@ -2150,6 +2165,7 @@ utils.createUUID = function () {
|
||||
UUIDcreatePart(6);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Extends a child object from a parent object using classical inheritance
|
||||
* pattern.
|
||||
@ -2178,6 +2194,10 @@ utils.alert = function (msg) {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
window.cordova = require('cordova');
|
||||
|
@ -1,5 +1,29 @@
|
||||
cordova.define('cordova/plugin_list', function(require, exports, module) {
|
||||
module.exports = [
|
||||
{
|
||||
"id": "cordova-plugin-browsertab.BrowserTab",
|
||||
"file": "plugins/cordova-plugin-browsertab/www/browsertab.js",
|
||||
"pluginId": "cordova-plugin-browsertab",
|
||||
"clobbers": [
|
||||
"cordova.plugins.browsertab"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "cordova-plugin-buildinfo.BuildInfo",
|
||||
"file": "plugins/cordova-plugin-buildinfo/www/buildinfo.js",
|
||||
"pluginId": "cordova-plugin-buildinfo",
|
||||
"clobbers": [
|
||||
"BuildInfo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "cordova-plugin-customurlscheme.LaunchMyApp",
|
||||
"file": "plugins/cordova-plugin-customurlscheme/www/android/LaunchMyApp.js",
|
||||
"pluginId": "cordova-plugin-customurlscheme",
|
||||
"clobbers": [
|
||||
"window.plugins.launchmyapp"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "cordova-plugin-device.device",
|
||||
"file": "plugins/cordova-plugin-device/www/device.js",
|
||||
@ -8,6 +32,15 @@ module.exports = [
|
||||
"device"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "cordova-plugin-inappbrowser.inappbrowser",
|
||||
"file": "plugins/cordova-plugin-inappbrowser/www/inappbrowser.js",
|
||||
"pluginId": "cordova-plugin-inappbrowser",
|
||||
"clobbers": [
|
||||
"cordova.InAppBrowser.open",
|
||||
"window.open"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "cordova-plugin-splashscreen.SplashScreen",
|
||||
"file": "plugins/cordova-plugin-splashscreen/www/splashscreen.js",
|
||||
@ -24,23 +57,6 @@ module.exports = [
|
||||
"window.StatusBar"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "ionic-plugin-keyboard.keyboard",
|
||||
"file": "plugins/ionic-plugin-keyboard/www/android/keyboard.js",
|
||||
"pluginId": "ionic-plugin-keyboard",
|
||||
"clobbers": [
|
||||
"cordova.plugins.Keyboard"
|
||||
],
|
||||
"runs": true
|
||||
},
|
||||
{
|
||||
"id": "cordova-plugin-buildinfo.BuildInfo",
|
||||
"file": "plugins/cordova-plugin-buildinfo/www/buildinfo.js",
|
||||
"pluginId": "cordova-plugin-buildinfo",
|
||||
"clobbers": [
|
||||
"BuildInfo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "cordova-universal-links-plugin.universalLinks",
|
||||
"file": "plugins/cordova-universal-links-plugin/www/universal_links.js",
|
||||
@ -50,46 +66,31 @@ module.exports = [
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "cordova-plugin-browsertab.BrowserTab",
|
||||
"file": "plugins/cordova-plugin-browsertab/www/browsertab.js",
|
||||
"pluginId": "cordova-plugin-browsertab",
|
||||
"id": "ionic-plugin-keyboard.keyboard",
|
||||
"file": "plugins/ionic-plugin-keyboard/www/android/keyboard.js",
|
||||
"pluginId": "ionic-plugin-keyboard",
|
||||
"clobbers": [
|
||||
"cordova.plugins.browsertab"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "cordova-plugin-inappbrowser.inappbrowser",
|
||||
"file": "plugins/cordova-plugin-inappbrowser/www/inappbrowser.js",
|
||||
"pluginId": "cordova-plugin-inappbrowser",
|
||||
"clobbers": [
|
||||
"cordova.InAppBrowser.open",
|
||||
"window.open"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "cordova-plugin-customurlscheme.LaunchMyApp",
|
||||
"file": "plugins/cordova-plugin-customurlscheme/www/android/LaunchMyApp.js",
|
||||
"pluginId": "cordova-plugin-customurlscheme",
|
||||
"clobbers": [
|
||||
"window.plugins.launchmyapp"
|
||||
]
|
||||
"cordova.plugins.Keyboard"
|
||||
],
|
||||
"runs": true
|
||||
}
|
||||
];
|
||||
module.exports.metadata =
|
||||
// TOP OF METADATA
|
||||
{
|
||||
"cordova-plugin-compat": "1.2.0",
|
||||
"cordova-plugin-browsertab": "0.2.0",
|
||||
"cordova-plugin-buildinfo": "2.0.1",
|
||||
"cordova-plugin-console": "1.1.0",
|
||||
"cordova-plugin-crosswalk-webview": "2.3.0",
|
||||
"cordova-plugin-customurlscheme": "4.3.0",
|
||||
"cordova-plugin-device": "1.1.7",
|
||||
"cordova-plugin-inappbrowser": "2.0.1",
|
||||
"cordova-plugin-splashscreen": "4.1.0",
|
||||
"cordova-plugin-statusbar": "2.4.1",
|
||||
"cordova-plugin-whitelist": "1.3.3",
|
||||
"ionic-plugin-keyboard": "2.2.1",
|
||||
"cordova-plugin-buildinfo": "2.0.1",
|
||||
"cordova-universal-links-plugin": "1.2.1",
|
||||
"cordova-plugin-browsertab": "0.2.0",
|
||||
"cordova-plugin-inappbrowser": "2.0.1",
|
||||
"cordova-plugin-customurlscheme": "4.3.0"
|
||||
"ionic-plugin-keyboard": "2.2.1"
|
||||
};
|
||||
// BOTTOM OF METADATA
|
||||
});
|
@ -1,17 +1,18 @@
|
||||
# This file was originally created by the Android Tools, but is now
|
||||
# used by cordova-android to manage the state of the various third party
|
||||
# libraries used in your application
|
||||
|
||||
# This is the Library Module that contains the Cordova Library, this is not
|
||||
# required when using an AAR
|
||||
|
||||
# This is the application project. This is only required for Android Studio Gradle projects
|
||||
|
||||
# This file is automatically generated by Android Tools.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must be checked in Version Control Systems.
|
||||
#
|
||||
# To customize properties used by the Ant build system edit
|
||||
# "ant.properties", and override values to adapt the script to your
|
||||
# project structure.
|
||||
#
|
||||
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
|
||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||
# Project target.
|
||||
target=android-26
|
||||
target=android-25
|
||||
android.library.reference.1=CordovaLib
|
||||
android.library.reference.2=app
|
||||
cordova.gradle.include.1=cordova-plugin-crosswalk-webview/dynamicbible-xwalk.gradle
|
||||
cordova.gradle.include.2=cordova-plugin-buildinfo/dynamicbible-BuildInfo.gradle
|
||||
cordova.system.library.1=com.android.support:customtabs:23.3.0
|
||||
cordova.gradle.include.3=cordova-plugin-browsertab/dynamicbible-BrowserTab.gradle
|
||||
cordova.gradle.include.1=cordova-plugin-browsertab/dynamicbible-BrowserTab.gradle
|
||||
cordova.gradle.include.2=cordova-plugin-buildinfo/dynamicbible-BuildInfo.gradle
|
||||
cordova.gradle.include.3=cordova-plugin-crosswalk-webview/dynamicbible-xwalk.gradle
|
After Width: | Height: | Size: 593 B |
After Width: | Height: | Size: 599 B |
After Width: | Height: | Size: 438 B |
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 99 KiB |
After Width: | Height: | Size: 132 KiB |
After Width: | Height: | Size: 172 KiB |
After Width: | Height: | Size: 427 B |
After Width: | Height: | Size: 438 B |
After Width: | Height: | Size: 328 B |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 98 KiB |
After Width: | Height: | Size: 131 KiB |
After Width: | Height: | Size: 171 KiB |
After Width: | Height: | Size: 727 B |
After Width: | Height: | Size: 744 B |
After Width: | Height: | Size: 536 B |
After Width: | Height: | Size: 1021 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 681 B |
BIN
DynamicBibleIonic/platforms/android/res/mipmap-hdpi/icon.png
Normal file
After Width: | Height: | Size: 5.0 KiB |
BIN
DynamicBibleIonic/platforms/android/res/mipmap-ldpi/icon.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
DynamicBibleIonic/platforms/android/res/mipmap-mdpi/icon.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
DynamicBibleIonic/platforms/android/res/mipmap-xhdpi/icon.png
Normal file
After Width: | Height: | Size: 6.7 KiB |
BIN
DynamicBibleIonic/platforms/android/res/mipmap-xxhdpi/icon.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
DynamicBibleIonic/platforms/android/res/mipmap-xxxhdpi/icon.png
Normal file
After Width: | Height: | Size: 14 KiB |
@ -0,0 +1,6 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<resources>
|
||||
<string name="app_name">Dynamic Bible</string>
|
||||
<string name="launcher_name">@string/app_name</string>
|
||||
<string name="activity_name">@string/launcher_name</string>
|
||||
</resources>
|
114
DynamicBibleIonic/platforms/android/res/xml/config.xml
Normal file
@ -0,0 +1,114 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<widget id="walljm.dynamicbible" version="3.0.3" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
|
||||
<feature name="BrowserTab">
|
||||
<param name="android-package" value="com.google.cordova.plugin.browsertab.BrowserTab" />
|
||||
</feature>
|
||||
<feature name="BuildInfo">
|
||||
<param name="android-package" value="org.apache.cordova.buildinfo.BuildInfo" />
|
||||
</feature>
|
||||
<feature name="LaunchMyApp">
|
||||
<param name="android-package" value="nl.xservices.plugins.LaunchMyApp" />
|
||||
</feature>
|
||||
<feature name="Device">
|
||||
<param name="android-package" value="org.apache.cordova.device.Device" />
|
||||
</feature>
|
||||
<feature name="InAppBrowser">
|
||||
<param name="android-package" value="org.apache.cordova.inappbrowser.InAppBrowser" />
|
||||
</feature>
|
||||
<feature name="SplashScreen">
|
||||
<param name="android-package" value="org.apache.cordova.splashscreen.SplashScreen" />
|
||||
<param name="onload" value="true" />
|
||||
</feature>
|
||||
<feature name="StatusBar">
|
||||
<param name="android-package" value="org.apache.cordova.statusbar.StatusBar" />
|
||||
<param name="onload" value="true" />
|
||||
</feature>
|
||||
<feature name="Whitelist">
|
||||
<param name="android-package" value="org.apache.cordova.whitelist.WhitelistPlugin" />
|
||||
<param name="onload" value="true" />
|
||||
</feature>
|
||||
<feature name="UniversalLinks">
|
||||
<param name="android-package" value="com.nordnetab.cordova.ul.UniversalLinksPlugin" />
|
||||
<param name="onload" value="true" />
|
||||
</feature>
|
||||
<feature name="Keyboard">
|
||||
<param name="android-package" value="io.ionic.keyboard.IonicKeyboard" />
|
||||
<param name="onload" value="true" />
|
||||
</feature>
|
||||
<name>Dynamic Bible</name>
|
||||
<description>A bible app designed for bible study</description>
|
||||
<author email="jason@walljm.com" href="http://dynamicbible.com/">Jason Wall</author>
|
||||
<content src="index.html" />
|
||||
<access origin="*" />
|
||||
<allow-intent href="http://*/*" />
|
||||
<allow-intent href="https://*/*" />
|
||||
<allow-intent href="tel:*" />
|
||||
<allow-intent href="sms:*" />
|
||||
<allow-intent href="mailto:*" />
|
||||
<allow-intent href="geo:*" />
|
||||
<universal-links>
|
||||
<host name="bhgx5.app.goo.gl/XktS" scheme="https" />
|
||||
<host name="dynamicbible-7c6cf.firebaseapp.com" scheme="https">
|
||||
<path url="/__/auth/callback" />
|
||||
</host>
|
||||
</universal-links>
|
||||
<allow-intent href="market:*" />
|
||||
<icon density="ldpi" src="resources\android\icon\drawable-ldpi-icon.png" />
|
||||
<icon density="mdpi" src="resources\android\icon\drawable-mdpi-icon.png" />
|
||||
<icon density="hdpi" src="resources\android\icon\drawable-hdpi-icon.png" />
|
||||
<icon density="xhdpi" src="resources\android\icon\drawable-xhdpi-icon.png" />
|
||||
<icon density="xxhdpi" src="resources\android\icon\drawable-xxhdpi-icon.png" />
|
||||
<icon density="xxxhdpi" src="resources\android\icon\drawable-xxxhdpi-icon.png" />
|
||||
<splash density="land-ldpi" src="resources\android\splash\drawable-land-ldpi-screen.png" />
|
||||
<splash density="land-mdpi" src="resources\android\splash\drawable-land-mdpi-screen.png" />
|
||||
<splash density="land-hdpi" src="resources\android\splash\drawable-land-hdpi-screen.png" />
|
||||
<splash density="land-xhdpi" src="resources\android\splash\drawable-land-xhdpi-screen.png" />
|
||||
<splash density="land-xxhdpi" src="resources\android\splash\drawable-land-xxhdpi-screen.png" />
|
||||
<splash density="land-xxxhdpi" src="resources\android\splash\drawable-land-xxxhdpi-screen.png" />
|
||||
<splash density="port-ldpi" src="resources\android\splash\drawable-port-ldpi-screen.png" />
|
||||
<splash density="port-mdpi" src="resources\android\splash\drawable-port-mdpi-screen.png" />
|
||||
<splash density="port-hdpi" src="resources\android\splash\drawable-port-hdpi-screen.png" />
|
||||
<splash density="port-xhdpi" src="resources\android\splash\drawable-port-xhdpi-screen.png" />
|
||||
<splash density="port-xxhdpi" src="resources\android\splash\drawable-port-xxhdpi-screen.png" />
|
||||
<splash density="port-xxxhdpi" src="resources\android\splash\drawable-port-xxxhdpi-screen.png" />
|
||||
<icon density="ldpi" src="resources/android/icon/drawable-ldpi-icon.png" />
|
||||
<icon density="mdpi" src="resources/android/icon/drawable-mdpi-icon.png" />
|
||||
<icon density="hdpi" src="resources/android/icon/drawable-hdpi-icon.png" />
|
||||
<icon density="xhdpi" src="resources/android/icon/drawable-xhdpi-icon.png" />
|
||||
<icon density="xxhdpi" src="resources/android/icon/drawable-xxhdpi-icon.png" />
|
||||
<icon density="xxxhdpi" src="resources/android/icon/drawable-xxxhdpi-icon.png" />
|
||||
<splash density="land-ldpi" src="resources/android/splash/drawable-land-ldpi-screen.png" />
|
||||
<splash density="land-mdpi" src="resources/android/splash/drawable-land-mdpi-screen.png" />
|
||||
<splash density="land-hdpi" src="resources/android/splash/drawable-land-hdpi-screen.png" />
|
||||
<splash density="land-xhdpi" src="resources/android/splash/drawable-land-xhdpi-screen.png" />
|
||||
<splash density="land-xxhdpi" src="resources/android/splash/drawable-land-xxhdpi-screen.png" />
|
||||
<splash density="land-xxxhdpi" src="resources/android/splash/drawable-land-xxxhdpi-screen.png" />
|
||||
<splash density="port-ldpi" src="resources/android/splash/drawable-port-ldpi-screen.png" />
|
||||
<splash density="port-mdpi" src="resources/android/splash/drawable-port-mdpi-screen.png" />
|
||||
<splash density="port-hdpi" src="resources/android/splash/drawable-port-hdpi-screen.png" />
|
||||
<splash density="port-xhdpi" src="resources/android/splash/drawable-port-xhdpi-screen.png" />
|
||||
<splash density="port-xxhdpi" src="resources/android/splash/drawable-port-xxhdpi-screen.png" />
|
||||
<splash density="port-xxxhdpi" src="resources/android/splash/drawable-port-xxxhdpi-screen.png" />
|
||||
<preference name="loglevel" value="DEBUG" />
|
||||
<preference name="webView" value="org.crosswalk.engine.XWalkWebViewEngine" />
|
||||
<preference name="xwalkVersion" value="23+" />
|
||||
<preference name="xwalkLiteVersion" value="xwalk_core_library_canary:17+" />
|
||||
<preference name="xwalkCommandLine" value="--disable-pull-to-refresh-effect" />
|
||||
<preference name="xwalkMode" value="embedded" />
|
||||
<preference name="xwalkMultipleApk" value="true" />
|
||||
<preference name="webviewbounce" value="false" />
|
||||
<preference name="UIWebViewBounce" value="false" />
|
||||
<preference name="DisallowOverscroll" value="true" />
|
||||
<preference name="android-minSdkVersion" value="16" />
|
||||
<preference name="BackupWebStorage" value="none" />
|
||||
<preference name="SplashMaintainAspectRatio" value="true" />
|
||||
<preference name="FadeSplashScreenDuration" value="300" />
|
||||
<preference name="SplashScreen" value="screen" />
|
||||
<preference name="SplashScreenDelay" value="12000" />
|
||||
<preference name="ShowSplashScreen" value="true" />
|
||||
<preference name="AutoHideSplashScreen" value="false" />
|
||||
<preference name="SplashShowOnlyFirstTime" value="false" />
|
||||
<preference name="FadeSplashScreen" value="false" />
|
||||
<preference name="loadUrlTimeoutValue" value="60000" />
|
||||
<preference name="AndroidLaunchMode" value="singleTask" />
|
||||
</widget>
|
@ -1,4 +1,3 @@
|
||||
// GENERATED FILE - DO NOT EDIT
|
||||
include ":"
|
||||
include ":CordovaLib"
|
||||
include ":app"
|
||||
|
@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright 2016 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Licensed 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 com.google.cordova.plugin.browsertab;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.net.Uri;
|
||||
import android.support.customtabs.CustomTabsIntent;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cordova.CallbackContext;
|
||||
import org.apache.cordova.CordovaInterface;
|
||||
import org.apache.cordova.CordovaPlugin;
|
||||
import org.apache.cordova.CordovaWebView;
|
||||
import org.apache.cordova.PluginResult;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* Cordova plugin which provides the ability to launch a URL in an
|
||||
* in-app browser tab. On Android, this means using the custom tabs support
|
||||
* library, if a supporting browser (e.g. Chrome) is available on the device.
|
||||
*/
|
||||
public class BrowserTab extends CordovaPlugin {
|
||||
|
||||
public static final int RC_OPEN_URL = 101;
|
||||
|
||||
private static final String LOG_TAG = "BrowserTab";
|
||||
|
||||
/**
|
||||
* The service we expect to find on a web browser that indicates it supports custom tabs.
|
||||
*/
|
||||
private static final String ACTION_CUSTOM_TABS_CONNECTION =
|
||||
"android.support.customtabs.action.CustomTabsService";
|
||||
|
||||
private boolean mFindCalled = false;
|
||||
private String mCustomTabsBrowser;
|
||||
|
||||
@Override
|
||||
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) {
|
||||
Log.d(LOG_TAG, "executing " + action);
|
||||
if ("isAvailable".equals(action)) {
|
||||
isAvailable(callbackContext);
|
||||
} else if ("openUrl".equals(action)) {
|
||||
openUrl(args, callbackContext);
|
||||
} else if ("close".equals(action)) {
|
||||
// close is a NOP on Android
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void isAvailable(CallbackContext callbackContext) {
|
||||
String browserPackage = findCustomTabBrowser();
|
||||
Log.d(LOG_TAG, "browser package: " + browserPackage);
|
||||
callbackContext.sendPluginResult(new PluginResult(
|
||||
PluginResult.Status.OK,
|
||||
browserPackage != null));
|
||||
}
|
||||
|
||||
private void openUrl(JSONArray args, CallbackContext callbackContext) {
|
||||
if (args.length() < 1) {
|
||||
Log.d(LOG_TAG, "openUrl: no url argument received");
|
||||
callbackContext.error("URL argument missing");
|
||||
return;
|
||||
}
|
||||
|
||||
String urlStr;
|
||||
try {
|
||||
urlStr = args.getString(0);
|
||||
} catch (JSONException e) {
|
||||
Log.d(LOG_TAG, "openUrl: failed to parse url argument");
|
||||
callbackContext.error("URL argument is not a string");
|
||||
return;
|
||||
}
|
||||
|
||||
String customTabsBrowser = findCustomTabBrowser();
|
||||
if (customTabsBrowser == null) {
|
||||
Log.d(LOG_TAG, "openUrl: no in app browser tab available");
|
||||
callbackContext.error("no in app browser tab implementation available");
|
||||
}
|
||||
|
||||
Intent customTabsIntent = new CustomTabsIntent.Builder().build().intent;
|
||||
customTabsIntent.setData(Uri.parse(urlStr));
|
||||
customTabsIntent.setPackage(mCustomTabsBrowser);
|
||||
cordova.getActivity().startActivity(customTabsIntent);
|
||||
|
||||
Log.d(LOG_TAG, "in app browser call dispatched");
|
||||
callbackContext.success();
|
||||
}
|
||||
|
||||
private String findCustomTabBrowser() {
|
||||
if (mFindCalled) {
|
||||
return mCustomTabsBrowser;
|
||||
}
|
||||
|
||||
PackageManager pm = cordova.getActivity().getPackageManager();
|
||||
Intent webIntent = new Intent(
|
||||
Intent.ACTION_VIEW,
|
||||
Uri.parse("http://www.example.com"));
|
||||
List<ResolveInfo> resolvedActivityList =
|
||||
pm.queryIntentActivities(webIntent, PackageManager.GET_RESOLVED_FILTER);
|
||||
|
||||
for (ResolveInfo info : resolvedActivityList) {
|
||||
if (!isFullBrowser(info)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hasCustomTabWarmupService(pm, info.activityInfo.packageName)) {
|
||||
mCustomTabsBrowser = info.activityInfo.packageName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mFindCalled = true;
|
||||
return mCustomTabsBrowser;
|
||||
}
|
||||
|
||||
private boolean isFullBrowser(ResolveInfo resolveInfo) {
|
||||
// The filter must match ACTION_VIEW, CATEGORY_BROWSEABLE, and at least one scheme,
|
||||
if (!resolveInfo.filter.hasAction(Intent.ACTION_VIEW)
|
||||
|| !resolveInfo.filter.hasCategory(Intent.CATEGORY_BROWSABLE)
|
||||
|| resolveInfo.filter.schemesIterator() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The filter must not be restricted to any particular set of authorities
|
||||
if (resolveInfo.filter.authoritiesIterator() != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The filter must support both HTTP and HTTPS.
|
||||
boolean supportsHttp = false;
|
||||
boolean supportsHttps = false;
|
||||
Iterator<String> schemeIter = resolveInfo.filter.schemesIterator();
|
||||
while (schemeIter.hasNext()) {
|
||||
String scheme = schemeIter.next();
|
||||
supportsHttp |= "http".equals(scheme);
|
||||
supportsHttps |= "https".equals(scheme);
|
||||
|
||||
if (supportsHttp && supportsHttps) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// at least one of HTTP or HTTPS is not supported
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean hasCustomTabWarmupService(PackageManager pm, String packageName) {
|
||||
Intent serviceIntent = new Intent();
|
||||
serviceIntent.setAction(ACTION_CUSTOM_TABS_CONNECTION);
|
||||
serviceIntent.setPackage(packageName);
|
||||
return (pm.resolveService(serviceIntent, 0) != null);
|
||||
}
|
||||
}
|
@ -0,0 +1,221 @@
|
||||
package com.nordnetab.cordova.ul;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.nordnetab.cordova.ul.js.JSAction;
|
||||
import com.nordnetab.cordova.ul.model.JSMessage;
|
||||
import com.nordnetab.cordova.ul.model.ULHost;
|
||||
import com.nordnetab.cordova.ul.parser.ULConfigXmlParser;
|
||||
|
||||
import org.apache.cordova.CallbackContext;
|
||||
import org.apache.cordova.CordovaArgs;
|
||||
import org.apache.cordova.CordovaInterface;
|
||||
import org.apache.cordova.CordovaPlugin;
|
||||
import org.apache.cordova.CordovaWebView;
|
||||
import org.apache.cordova.PluginResult;
|
||||
import org.json.JSONException;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by Nikolay Demyankov on 09.09.15.
|
||||
* <p/>
|
||||
* Plugin main class.
|
||||
* Communicates with the JS side, handles launch intents and so on.
|
||||
*/
|
||||
public class UniversalLinksPlugin extends CordovaPlugin {
|
||||
|
||||
// list of hosts, defined in config.xml
|
||||
private List<ULHost> supportedHosts;
|
||||
|
||||
// list of subscribers
|
||||
private Map<String, CallbackContext> subscribers;
|
||||
|
||||
// stored message, that is captured on application launch
|
||||
private JSMessage storedMessage;
|
||||
|
||||
// region Public API
|
||||
|
||||
@Override
|
||||
public void initialize(CordovaInterface cordova, CordovaWebView webView) {
|
||||
super.initialize(cordova, webView);
|
||||
|
||||
supportedHosts = new ULConfigXmlParser(cordova.getActivity()).parse();
|
||||
|
||||
if (subscribers == null) {
|
||||
subscribers = new HashMap<String, CallbackContext>();
|
||||
}
|
||||
|
||||
handleIntent(cordova.getActivity().getIntent());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(String action, CordovaArgs args, CallbackContext callbackContext) throws JSONException {
|
||||
boolean isHandled = true;
|
||||
if (JSAction.SUBSCRIBE.equals(action)) {
|
||||
subscribeForEvent(args, callbackContext);
|
||||
} else if (JSAction.UNSUBSCRIBE.equals(action)) {
|
||||
unsubscribeFromEvent(args);
|
||||
} else {
|
||||
isHandled = false;
|
||||
}
|
||||
|
||||
return isHandled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewIntent(Intent intent) {
|
||||
handleIntent(intent);
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region JavaScript methods
|
||||
|
||||
/**
|
||||
* Add subscriber for the event.
|
||||
*
|
||||
* @param arguments arguments, passed from JS side
|
||||
* @param callbackContext callback to use when event is captured
|
||||
*/
|
||||
private void subscribeForEvent(final CordovaArgs arguments, final CallbackContext callbackContext) {
|
||||
final String eventName = getEventNameFromArguments(arguments);
|
||||
if (TextUtils.isEmpty(eventName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
subscribers.put(eventName, callbackContext);
|
||||
tryToConsumeEvent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove subscriber from the event.
|
||||
*
|
||||
* @param arguments arguments, passed from JS side
|
||||
*/
|
||||
private void unsubscribeFromEvent(final CordovaArgs arguments) {
|
||||
if (subscribers.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String eventName = getEventNameFromArguments(arguments);
|
||||
if (TextUtils.isEmpty(eventName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
subscribers.remove(eventName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get event name from the cordova arguments.
|
||||
*
|
||||
* @param arguments received arguments
|
||||
* @return event name; <code>null</code> if non is found
|
||||
*/
|
||||
private String getEventNameFromArguments(final CordovaArgs arguments) {
|
||||
String eventName = null;
|
||||
try {
|
||||
eventName = arguments.getString(0);
|
||||
} catch (JSONException e) {
|
||||
Log.d("UniversalLinks", "Failed to get event name from the JS arguments", e);
|
||||
}
|
||||
|
||||
return eventName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to send event to the subscribers.
|
||||
*/
|
||||
private void tryToConsumeEvent() {
|
||||
if (subscribers.size() == 0 || storedMessage == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String storedEventName = storedMessage.getEventName();
|
||||
final Set<Map.Entry<String, CallbackContext>> subscribersSet = subscribers.entrySet();
|
||||
for (Map.Entry<String, CallbackContext> subscriber : subscribersSet) {
|
||||
final String eventName = subscriber.getKey();
|
||||
if (eventName.equals(storedEventName)) {
|
||||
sendMessageToJs(storedMessage, subscriber.getValue());
|
||||
storedMessage = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send message to JS side.
|
||||
*
|
||||
* @param message message to send
|
||||
* @param callback to what callback we are sending the message
|
||||
*/
|
||||
private void sendMessageToJs(JSMessage message, CallbackContext callback) {
|
||||
final PluginResult result = new PluginResult(PluginResult.Status.OK, message);
|
||||
result.setKeepCallback(true);
|
||||
callback.sendPluginResult(result);
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Intent handling
|
||||
|
||||
/**
|
||||
* Handle launch intent.
|
||||
* If it is an UL intent - then event will be dispatched to the JS side.
|
||||
*
|
||||
* @param intent launch intent
|
||||
*/
|
||||
private void handleIntent(Intent intent) {
|
||||
if (intent == null || supportedHosts == null || supportedHosts.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// read intent
|
||||
String action = intent.getAction();
|
||||
Uri launchUri = intent.getData();
|
||||
|
||||
// if app was not launched by the url - ignore
|
||||
if (!Intent.ACTION_VIEW.equals(action) || launchUri == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// try to find host in the hosts list from the config.xml
|
||||
ULHost host = findHostByUrl(launchUri);
|
||||
if (host == null) {
|
||||
Log.d("UniversalLinks", "Host " + launchUri.getHost() + " is not supported");
|
||||
return;
|
||||
}
|
||||
|
||||
// store message and try to consume it
|
||||
storedMessage = new JSMessage(host, launchUri);
|
||||
tryToConsumeEvent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find host entry that matches the launch url.
|
||||
*
|
||||
* @param url launch url
|
||||
* @return host entry; <code>null</code> - if none were found
|
||||
*/
|
||||
private ULHost findHostByUrl(Uri url) {
|
||||
ULHost host = null;
|
||||
final String launchHost = url.getHost().toLowerCase();
|
||||
for (ULHost supportedHost : supportedHosts) {
|
||||
if (supportedHost.getName().equals(launchHost) ||
|
||||
supportedHost.getName().startsWith("*.") && launchHost.endsWith(supportedHost.getName().substring(1))) {
|
||||
host = supportedHost;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return host;
|
||||
}
|
||||
|
||||
// endregion
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package com.nordnetab.cordova.ul.js;
|
||||
|
||||
/**
|
||||
* Created by Nikolay Demyankov on 09.09.15.
|
||||
* <p/>
|
||||
* Class holds list of method names that is called from JS side.
|
||||
*/
|
||||
public final class JSAction {
|
||||
|
||||
/**
|
||||
* Subscribe to event.
|
||||
*/
|
||||
public static final String SUBSCRIBE = "jsSubscribeForEvent";
|
||||
|
||||
/**
|
||||
* Unsubscribe from event.
|
||||
*/
|
||||
public static final String UNSUBSCRIBE = "jsUnsubscribeFromEvent";
|
||||
}
|
@ -0,0 +1,193 @@
|
||||
package com.nordnetab.cordova.ul.model;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by Nikolay Demyankov on 10.09.15.
|
||||
* <p/>
|
||||
* Model for the message entry, that is send to JS.
|
||||
*/
|
||||
public class JSMessage extends JSONObject {
|
||||
|
||||
// keys for the message base structure
|
||||
private static final class JSGeneralKeys {
|
||||
/**
|
||||
* Event name
|
||||
*/
|
||||
public static final String EVENT = "event";
|
||||
|
||||
/**
|
||||
* Message data block
|
||||
*/
|
||||
public static final String DATA = "data";
|
||||
}
|
||||
|
||||
// keys for the message data block
|
||||
private static final class JSDataKeys {
|
||||
|
||||
/**
|
||||
* Path part of the url
|
||||
*/
|
||||
public static final String PATH = "path";
|
||||
|
||||
/**
|
||||
* Scheme of the url
|
||||
*/
|
||||
public static final String SCHEME = "scheme";
|
||||
|
||||
/**
|
||||
* Host of the url
|
||||
*/
|
||||
public static final String HOST = "host";
|
||||
|
||||
/**
|
||||
* Hash (fragment) from the url - data after '#'
|
||||
*/
|
||||
public static final String HASH = "hash";
|
||||
|
||||
/**
|
||||
* Query parameters - data after '?'
|
||||
*/
|
||||
public static final String PARAMS = "params";
|
||||
|
||||
/**
|
||||
* Launch url as it is
|
||||
*/
|
||||
public static final String ORIGIN = "url";
|
||||
}
|
||||
|
||||
private String eventName;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param host host entry that corresponds to the launching url
|
||||
* @param originalUri launch url
|
||||
*/
|
||||
public JSMessage(ULHost host, Uri originalUri) {
|
||||
setEventName(host, originalUri);
|
||||
setMessageData(host, originalUri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for event name of this message.
|
||||
*
|
||||
* @return event name
|
||||
*/
|
||||
public String getEventName() {
|
||||
return eventName;
|
||||
}
|
||||
|
||||
// region Event name setters
|
||||
|
||||
/**
|
||||
* Set event name for this message entry.
|
||||
*/
|
||||
private void setEventName(ULHost host, Uri originalUri) {
|
||||
eventName = getEventName(host, originalUri);
|
||||
|
||||
try {
|
||||
put(JSGeneralKeys.EVENT, eventName);
|
||||
} catch (JSONException e) {
|
||||
Log.d("UniversalLinks", "Failed to set event name", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find event name based on the launching url.
|
||||
* By default, event name from the host object will be used.
|
||||
* But if we have some path entry in the host and it matches the one from the launch url - his event name will be used.
|
||||
*/
|
||||
private String getEventName(ULHost host, Uri originalUri) {
|
||||
String event = host.getEvent();
|
||||
final String originPath = originalUri.getPath().toLowerCase();
|
||||
final List<ULPath> hostPathsList = host.getPaths();
|
||||
for (ULPath hostPath : hostPathsList) {
|
||||
final String hostPathUrl = hostPath.getUrl();
|
||||
if (hostPathUrl == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (originPath.matches(hostPathUrl)) {
|
||||
event = hostPath.getEvent();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Data block setters
|
||||
|
||||
/**
|
||||
* Fill data block with corresponding information.
|
||||
*/
|
||||
private void setMessageData(ULHost host, Uri originalUri) {
|
||||
final JSONObject dataObject = new JSONObject();
|
||||
|
||||
try {
|
||||
setOriginalUrl(dataObject, originalUri);
|
||||
setHostData(dataObject, host);
|
||||
setPathData(dataObject, originalUri);
|
||||
|
||||
put(JSGeneralKeys.DATA, dataObject);
|
||||
} catch (JSONException e) {
|
||||
Log.d("UniversalLinks", "Failed to set event data", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Put launch url to the data block
|
||||
*/
|
||||
private void setOriginalUrl(JSONObject dataObject, Uri originalUri) throws JSONException {
|
||||
dataObject.put(JSDataKeys.ORIGIN, originalUri.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Put host name and scheme into data block
|
||||
*/
|
||||
private void setHostData(JSONObject dataObject, ULHost host) throws JSONException {
|
||||
dataObject.put(JSDataKeys.HOST, host.getName());
|
||||
dataObject.put(JSDataKeys.SCHEME, host.getScheme());
|
||||
}
|
||||
|
||||
/**
|
||||
* Put path information into data block
|
||||
*/
|
||||
private void setPathData(JSONObject dataObject, Uri originalUri) throws JSONException {
|
||||
dataObject.put(JSDataKeys.HASH, originalUri.getFragment());
|
||||
dataObject.put(JSDataKeys.PATH, originalUri.getPath());
|
||||
|
||||
final JSONObject queryParams = getQueryParamsFromUri(originalUri);
|
||||
dataObject.put(JSDataKeys.PARAMS, queryParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse query params.
|
||||
* For example, if we have link like so: http://somedomain.com/some/path?foo=fooVal&bar=barVal , then
|
||||
* resulting object will be {foo: fooVal, bar: barVal}.
|
||||
*
|
||||
* @return json object
|
||||
*/
|
||||
private JSONObject getQueryParamsFromUri(Uri originalUri) throws JSONException, UnsupportedOperationException {
|
||||
JSONObject queryParams = new JSONObject();
|
||||
Set<String> keysList = originalUri.getQueryParameterNames();
|
||||
for (String key : keysList) {
|
||||
final String value = originalUri.getQueryParameter(key);
|
||||
queryParams.put(key, value);
|
||||
}
|
||||
|
||||
return queryParams;
|
||||
}
|
||||
|
||||
// endregion
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
package com.nordnetab.cordova.ul.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Nikolay Demyankov on 09.09.15.
|
||||
* <p/>
|
||||
* Model for <host /> entry, specified in config.xml.
|
||||
*/
|
||||
public class ULHost {
|
||||
|
||||
// default event name, that is dispatched to JS if none was set to the host or path
|
||||
private static final String DEFAULT_EVENT = "didLaunchAppFromLink";
|
||||
|
||||
// default scheme for the host
|
||||
private static final String DEFAULT_SCHEME = "http";
|
||||
|
||||
private final List<ULPath> paths;
|
||||
private final String name;
|
||||
private final String scheme;
|
||||
private String event;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param name host name
|
||||
* @param scheme host scheme
|
||||
* @param event event that corresponds to this host
|
||||
*/
|
||||
public ULHost(final String name, final String scheme, final String event) {
|
||||
this.name = name.toLowerCase();
|
||||
this.scheme = (scheme == null) ? DEFAULT_SCHEME : scheme;
|
||||
this.event = (event == null) ? DEFAULT_EVENT : event;
|
||||
this.paths = new ArrayList<ULPath>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the event name that is sent to JS when user clicks on the link from this host.
|
||||
* Defined as 'event' attribute.
|
||||
*
|
||||
* @return event name
|
||||
*/
|
||||
public String getEvent() {
|
||||
return event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for event name.
|
||||
*
|
||||
* @param event event name
|
||||
*/
|
||||
public void setEvent(final String event) {
|
||||
this.event = event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the list of paths, that is set for that host in config.xml.
|
||||
*
|
||||
* @return list of hosts
|
||||
*/
|
||||
public List<ULPath> getPaths() {
|
||||
return paths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the host name.
|
||||
* Defined as 'name' attribute.
|
||||
*
|
||||
* @return host name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for host scheme.
|
||||
* Defined as 'scheme' attribute.
|
||||
*
|
||||
* @return scheme
|
||||
*/
|
||||
public String getScheme() {
|
||||
return scheme;
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package com.nordnetab.cordova.ul.model;
|
||||
|
||||
/**
|
||||
* Created by Nikolay Demyankov on 09.09.15.
|
||||
* <p/>
|
||||
* Model for <path /> entry for host in config.xml
|
||||
*/
|
||||
public class ULPath {
|
||||
|
||||
private final String url;
|
||||
private final String event;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param url path url
|
||||
* @param event event name
|
||||
*/
|
||||
public ULPath(final String url, final String event) {
|
||||
this.url = url.replace("*", "(.*)").toLowerCase();
|
||||
this.event = event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for path url.
|
||||
* Defined as 'url' attribute.
|
||||
*
|
||||
* @return path url
|
||||
*/
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the event name that is dispatched when application is launched from the link with this path.
|
||||
* Defined as 'event' attribute.
|
||||
*
|
||||
* @return event name
|
||||
*/
|
||||
public String getEvent() {
|
||||
return event;
|
||||
}
|
||||
}
|
@ -0,0 +1,156 @@
|
||||
package com.nordnetab.cordova.ul.parser;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.nordnetab.cordova.ul.model.ULHost;
|
||||
import com.nordnetab.cordova.ul.model.ULPath;
|
||||
|
||||
import org.apache.cordova.ConfigXmlParser;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Nikolay Demyankov on 09.09.15.
|
||||
* <p/>
|
||||
* Parser for config.xml. Reads only plugin-specific preferences.
|
||||
*/
|
||||
public class ULConfigXmlParser extends ConfigXmlParser {
|
||||
|
||||
private final Context context;
|
||||
private List<ULHost> hostsList;
|
||||
|
||||
private boolean isInsideMainTag;
|
||||
private boolean didParseMainBlock;
|
||||
private boolean isInsideHostBlock;
|
||||
private ULHost processedHost;
|
||||
|
||||
// region Public API
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param context application context
|
||||
*/
|
||||
public ULConfigXmlParser(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse config.xml
|
||||
*
|
||||
* @return list of hosts, defined in the config file
|
||||
*/
|
||||
public List<ULHost> parse() {
|
||||
resetValuesToDefaultState();
|
||||
super.parse(context);
|
||||
|
||||
return hostsList;
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region XML processing
|
||||
|
||||
@Override
|
||||
public void handleStartTag(XmlPullParser xml) {
|
||||
if (didParseMainBlock) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String name = xml.getName();
|
||||
if (!isInsideMainTag && XmlTags.MAIN_TAG.equals(name)) {
|
||||
isInsideMainTag = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isInsideMainTag) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isInsideHostBlock && XmlTags.HOST_TAG.equals(name)) {
|
||||
isInsideHostBlock = true;
|
||||
processHostBlock(xml);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isInsideHostBlock && XmlTags.PATH_TAG.equals(name)) {
|
||||
processPathBlock(xml);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleEndTag(XmlPullParser xml) {
|
||||
if (didParseMainBlock) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String name = xml.getName();
|
||||
|
||||
if (isInsideHostBlock && XmlTags.HOST_TAG.equals(name)) {
|
||||
isInsideHostBlock = false;
|
||||
hostsList.add(processedHost);
|
||||
processedHost = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (XmlTags.MAIN_TAG.equals(name)) {
|
||||
isInsideMainTag = false;
|
||||
didParseMainBlock = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse <host />
|
||||
*/
|
||||
private void processHostBlock(XmlPullParser xml) {
|
||||
final String hostName = xml.getAttributeValue(null, XmlTags.HOST_NAME_ATTRIBUTE);
|
||||
final String eventName = xml.getAttributeValue(null, XmlTags.HOST_EVENT_ATTRIBUTE);
|
||||
final String scheme = xml.getAttributeValue(null, XmlTags.HOST_SCHEME_ATTRIBUTE);
|
||||
|
||||
processedHost = new ULHost(hostName, scheme, eventName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse <path />
|
||||
*/
|
||||
private void processPathBlock(XmlPullParser xml) {
|
||||
final String url = xml.getAttributeValue(null, XmlTags.PATH_URL_TAG);
|
||||
String event = xml.getAttributeValue(null, XmlTags.PATH_EVENT_TAG);
|
||||
|
||||
// skip wildcard urls
|
||||
if ("*".equals(url) || ".*".equals(url)) {
|
||||
// but if path has event name - set it to host
|
||||
if (!TextUtils.isEmpty(event)) {
|
||||
processedHost.setEvent(event);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// if event name is empty - use one from the host
|
||||
if (TextUtils.isEmpty(event)) {
|
||||
event = processedHost.getEvent();
|
||||
}
|
||||
|
||||
// create path entry
|
||||
ULPath path = new ULPath(url, event);
|
||||
processedHost.getPaths().add(path);
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Private API
|
||||
|
||||
private void resetValuesToDefaultState() {
|
||||
hostsList = new ArrayList<ULHost>();
|
||||
isInsideMainTag = false;
|
||||
didParseMainBlock = false;
|
||||
isInsideHostBlock = false;
|
||||
processedHost = null;
|
||||
}
|
||||
|
||||
// endregion
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package com.nordnetab.cordova.ul.parser;
|
||||
|
||||
/**
|
||||
* Created by Nikolay Demyankov on 10.09.15.
|
||||
* <p/>
|
||||
* XML tags that is used in config.xml to specify plugin preferences.
|
||||
*/
|
||||
final class XmlTags {
|
||||
|
||||
/**
|
||||
* Main tag in which we define plugin related stuff
|
||||
*/
|
||||
public static final String MAIN_TAG = "universal-links";
|
||||
|
||||
/**
|
||||
* Host main tag
|
||||
*/
|
||||
public static final String HOST_TAG = "host";
|
||||
|
||||
/**
|
||||
* Scheme attribute for the host entry
|
||||
*/
|
||||
public static final String HOST_SCHEME_ATTRIBUTE = "scheme";
|
||||
|
||||
/**
|
||||
* Name attribute for the host entry
|
||||
*/
|
||||
public static final String HOST_NAME_ATTRIBUTE = "name";
|
||||
|
||||
/**
|
||||
* Event attribute for the host entry
|
||||
*/
|
||||
public static final String HOST_EVENT_ATTRIBUTE = "event";
|
||||
|
||||
/**
|
||||
* Path main tag
|
||||
*/
|
||||
public static final String PATH_TAG = "path";
|
||||
|
||||
/**
|
||||
* Url attribute for the path entry
|
||||
*/
|
||||
public static final String PATH_URL_TAG = "url";
|
||||
|
||||
/**
|
||||
* Event attribute for the path entry
|
||||
*/
|
||||
public static final String PATH_EVENT_TAG = "event";
|
||||
}
|