I've got a basic ReactJS Project and I followed this guide to turn it into an android project with my output in the build directory.
I've successfully generated a working APK file. however now I wish to point https://example.com/ URL opened by any browser on mobile to open my app once it's been installed. any help would be greatly apperiacted.
I'm not sure where to register this url to open my app, TIA
Update
<intent-filter android:label="#string/title_activity_main">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https"
android:host="m.clipdrop.io"
android:pathPrefix="/" />
</intent-filter>
<intent-filter android:label="#string/title_activity_main">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http"
android:host="m.clipdrop.io"
android:pathPrefix="/" />
</intent-filter>
<!-- Accepts URIs that begin with "clipdrop://login” -->
<intent-filter android:label="#string/title_activity_main">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="clipdrop"
android:host="login" />
</intent-filter>
The link clicked would look like this
https://m.clipdrop.io/login?b=datahere
then i have this code which handles the open url event
import React, { useEffect } from 'react';
import { useHistory } from 'react-router-dom';
import { App, URLOpenListenerEvent } from '#capacitor/app';
export default function AppUrlListener(){
let history = useHistory();
useEffect(() => {
App.addListener('appUrlOpen', (event) => {
var url = new URL(event.url);
var benc = url.searchParams.get("b")?.replace("%3D", "=");
if(benc){
window.location.href = "/login?b=" + benc;
}
// If no match, do nothing - let regular routing
// logic take over
});
}, []);
return null;
};
Update 2
File: AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.clipdrop.clipdrop">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode"
android:name="io.clipdrop.clipdrop.MainActivity"
android:label="#string/title_activity_main"
android:theme="#style/AppTheme.NoActionBarLaunch"
android:launchMode="singleTask"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<!-- Accepts URIs that begin with "http(s)://m.clipdrop.io -->
<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:scheme="http" />
<data android:scheme="https" />
<data android:host="m.clipdrop.io" />
</intent-filter>
</activity>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths"></meta-data>
</provider>
</application>
<!-- Permissions -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.MICROPHONE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-feature android:name="android.hardware.camera" android:required="true" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-feature android:name="android.hardware.microphone"/>
<uses-permission android:name="android.permission.AUDIO_CAPTURE" />
</manifest>
I have setup the assetlinks.json
when clicking the link it opens in the browser instead, but there is this icon in the corner when it opens in the browser:
If you are using Capacitor, for adding deeplinks to your project, follow the native procedure. just like explained in android docs, you should have this in your manifest file (located in android/app/src/main/AndroidManifest.xml):
<activity
android:name="com.example.android.GizmosActivity"
android:label="#string/title_gizmos" >
<intent-filter android:label="#string/filter_view_http_gizmos">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- **** -->
<!-- This is where you put your deeplinks with the 'data' tag: -->
<!-- **** -->
<!-- Accepts URIs that begin with "http://www.example.com/gizmos” -->
<data android:scheme="http"
android:host="www.example.com"
android:pathPrefix="/gizmos" />
<!-- note that the leading "/" is required for pathPrefix-->
<!-- **** -->
<!-- **** -->
</intent-filter>
<intent-filter android:label="#string/filter_view_example_gizmos">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Accepts URIs that begin with "example://gizmos” -->
<data android:scheme="example"
android:host="gizmos" />
</intent-filter>
</activity>
for handling deeplink requests and it's data inside of your app after it has been opened, use the appUrlOpen event as explained in capacitor docs
UPDATE
answer for your update:
Since android 12, deeplinks in android would directly open browser unless you verify your applink. follow this instructions for verifying app links.
Related
can this generate a syntax for url scheme, need help.
What is this (BOOT_COMPLETED, TIME_TRIGGER_ACTION, TIME_TRIGGER_ALLOW_IDLE_ACTION, MEDIA_CHANGE_ACTION, GEOFENCE_CHANGE_ACTION) to do need clarification
what is the purpose of string com.google.android.libraries.assistant.context trigger.impl.ContextTriggerBroadcastReceiver_Receiver
<receiver android:exported="false" android:name="com.google.android.libraries.assistant.contexttrigger.impl.ContextTriggerBroadcastReceiver_Receiver" android:process=":search">
<intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> <action android:name="TIME_TRIGGER_ACTION" /> <action android:name="TIME_TRIGGER_ALLOW_IDLE_ACTION" /> <action android:name="AWARENESS_ACTION_V1" /> <action android:name="AWARENESS_ACTION_V2" /> <action android:name="MEDIA_CHANGE_ACTION" /> <action android:name="GEOFENCE_CHANGE_ACTION" />
</intent-filter> </receiver>
When using phonegap build, whitelisting doesn't seem to be working. When I run the application from a browser, all the ajax calls are successfull and the application works. I have the following config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<widget xmlns="http://www.w3.org/ns/widgets" xmlns:gap="http://phonegap.com/ns/1.0"
id="com.company.Demo" version="1.0.0">
<name>Demo</name>
<description>
...
</description>
<author email="myEmailAddress">
Jeroen Claes
</author>
<content src="index.html" />
<preference name="phonegap-version" value="cli-5.2.0" />
<preference name="orientation" value="default" /> <!-- all: default means both landscape and portrait are enabled -->
<preference name="target-device" value="universal" /> <!-- all: possible values handset, tablet, or universal -->
<preference name="fullscreen" value="true" /> <!-- all: hides the status bar at the top of the screen -->
<preference name="webviewbounce" value="true" /> <!-- ios: control whether the screen 'bounces' when scrolled beyond the top -->
<preference name="prerendered-icon" value="true" /> <!-- ios: if icon is prerendered, iOS will not apply it's gloss to the app's icon on the user's home screen -->
<preference name="stay-in-webview" value="false" /> <!-- ios: external links should open in the default browser, 'true' would use the webview the app lives in -->
<preference name="ios-statusbarstyle" value="black-opaque" /> <!-- ios: black-translucent will appear black because the PhoneGap webview doesn't go beneath the status bar -->
<preference name="detect-data-types" value="true" /> <!-- ios: controls whether data types (such as phone no. and dates) are automatically turned into links by the system -->
<preference name="exit-on-suspend" value="false" /> <!-- ios: if set to true, app will terminate when home button is pressed -->
<preference name="show-splash-screen-spinner" value="true" /> <!-- ios: if set to false, the spinner won't appear on the splash screen during app loading -->
<preference name="auto-hide-splash-screen" value="true" /> <!-- ios: if set to false, the splash screen must be hidden using a JavaScript API -->
<preference name="disable-cursor" value="false" /> <!-- blackberry: prevents a mouse-icon/cursor from being displayed on the app -->
<preference name="android-installLocation" value="auto" /> <!-- android: app install location. 'auto' will choose. 'internalOnly' is device memory. 'preferExternal' is SDCard. -->
<!-- Plugins -->
<!-- Core plugins -->
<gap:plugin name="org.apache.cordova.battery-status" />
<gap:plugin name="org.apache.cordova.camera" />
<gap:plugin name="org.apache.cordova.media-capture" />
<gap:plugin name="org.apache.cordova.console" />
<gap:plugin name="org.apache.cordova.contacts" />
<gap:plugin name="org.apache.cordova.device" />
<gap:plugin name="org.apache.cordova.device-motion" />
<gap:plugin name="org.apache.cordova.device-orientation" />
<gap:plugin name="org.apache.cordova.dialogs" />
<gap:plugin name="org.apache.cordova.file" />
<gap:plugin name="org.apache.cordova.file-transfer" />
<gap:plugin name="org.apache.cordova.geolocation" />
<gap:plugin name="org.apache.cordova.globalization" />
<gap:plugin name="org.apache.cordova.inappbrowser" />
<gap:plugin name="org.apache.cordova.media" />
<gap:plugin name="org.apache.cordova.network-information" />
<gap:plugin name="org.apache.cordova.splashscreen" />
<gap:plugin name="org.apache.cordova.vibration" />
<gap:plugin name="cordova-plugin-whitelist" source="npm"/>
<!-- Third party plugins -->
<!-- A list of available plugins are available at https://build.phonegap.com/plugins -->
<!-- Define app icon for each platform. -->
<icon src="icon.png" />
<icon src="res/icon/android/icon-36-ldpi.png" gap:platform="android" gap:qualifier="ldpi" />
<icon src="res/icon/android/icon-48-mdpi.png" gap:platform="android" gap:qualifier="mdpi" />
<icon src="res/icon/android/icon-72-hdpi.png" gap:platform="android" gap:qualifier="hdpi" />
<icon src="res/icon/android/icon-96-xhdpi.png" gap:platform="android" gap:qualifier="xhdpi" />
<icon src="res/icon/blackberry/icon-80.png" gap:platform="blackberry" />
<icon src="res/icon/blackberry/icon-80.png" gap:platform="blackberry" gap:state="hover"/>
<icon src="res/icon/ios/icon-57.png" gap:platform="ios" width="57" height="57" />
<icon src="res/icon/ios/icon-72.png" gap:platform="ios" width="72" height="72" />
<icon src="res/icon/ios/icon-57-2x.png" gap:platform="ios" width="114" height="114" />
<icon src="res/icon/ios/icon-72-2x.png" gap:platform="ios" width="144" height="144" />
<icon src="res/icon/webos/icon-64.png" gap:platform="webos" />
<icon src="res/icon/windows-phone/icon-48.png" gap:platform="winphone" />
<icon src="res/icon/windows-phone/icon-173.png" gap:platform="winphone" gap:role="background" />
<!-- Define app splash screen for each platform. -->
<gap:splash src="res/screen/android/screen-ldpi-portrait.png" gap:platform="android" gap:qualifier="port-ldpi" />
<gap:splash src="res/screen/android/screen-mdpi-portrait.png" gap:platform="android" gap:qualifier="port-mdpi" />
<gap:splash src="res/screen/android/screen-hdpi-portrait.png" gap:platform="android" gap:qualifier="port-hdpi" />
<gap:splash src="res/screen/android/screen-xhdpi-portrait.png" gap:platform="android" gap:qualifier="port-xhdpi" />
<gap:splash src="res/screen/blackberry/screen-225.png" gap:platform="blackberry" />
<gap:splash src="res/screen/ios/screen-iphone-portrait.png" gap:platform="ios" width="320" height="480" />
<gap:splash src="res/screen/ios/screen-iphone-portrait-2x.png" gap:platform="ios" width="640" height="960" />
<gap:splash src="res/screen/ios/screen-iphone-portrait-568h-2x.png" gap:platform="ios" width="640" height="1136" />
<gap:splash src="res/screen/ios/screen-ipad-portrait.png" gap:platform="ios" width="768" height="1024" />
<gap:splash src="res/screen/ios/screen-ipad-landscape.png" gap:platform="ios" width="1024" height="768" />
<gap:splash src="res/screen/windows-phone/screen-portrait.jpg" gap:platform="winphone" />
<access origin="*" />
<allow-intent href="*" />
<allow-navigation href="*" />
<!-- Added the following intents to support the removal of whitelist code from base cordova to a plugin -->
<!-- Whitelist configuration. Refer to https://cordova.apache.org/docs/en/edge/guide_appdev_whitelist_index.md.html -->
<!-- <allow-intent href="http://*/*" /> -->
<!-- <allow-intent href="https://*/*" /> -->
<!-- <allow-intent href="tel:*" /> -->
<!-- <allow-intent href="sms:*" /> -->
<!-- <allow-intent href="mailto:*" /> -->
<!-- <allow-intent href="geo:*" /> -->
<!-- <allow-intent href="*" /> -->
<platform name="android">
<allow-intent href="market:*" />
</platform>
<platform name="ios">
<allow-intent href="itms:*" />
<allow-intent href="itms-apps:*" />
</platform>
<platform name="winphone">
</platform>
</widget>
I've also added the following to my index.html:
<meta http-equiv="Content-Security-Policy" content="default-src *; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'">
I'm even using the following params before sending my jquery post to the server:
$.support.cors = true;
$.mobile.allowCrossDomainPages = true;
Each time I send an ajax request I receive a 403 error: forbidden
This is the ajax request I'm sending:
var sr = "<?xml version='1.0' encoding='UTF-8'?>";
sr += "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" >";
sr += "<soap:Body>";
sr += "<wsse:Username>" + username + "</wsse:Username>";
sr += "<wsse:Password>" + password + "</wsse:Password>";
sr += "<\/soap:Body>";
sr += "<\/soap:Envelope>";
$.ajax({
headers: { 'SOAPAction': "\"Login\""
},
url:"https://host:port/demo/Login",
type: "POST",
contentType: "text/xml; charset=utf-8",
accepts:"application/xml; text/xml; \*/\*",
dataType: "json",
crossDomain: true,
data: sr,
processData: false,
success: function(resp){...},
fail: function(err){...}});
#Jeroen,
CORS or 'Access-Control-Allow-Origin' is not required. This is a common misconception with Phonegap. 'CORS' is a wevbrowser security protocol. It is not a Mobile App security protocol.
To be clear, the webview library used for Cordova/Phonega renders HTML, but it is NOT a webbrowser. The wikipedia explanation for CORS is half-bad, but the explanation works. CORS always starts with a webbrowser that is capable of CORS. Again, CORS does NOT exist on Cordova/Phonegap.
This FAQ should also help.
Top Mistakes by Developers new to Cordova/Phonegap see: #5
Your connections issue in the CSP. This is also a common mistake, mostly because all the examples are poor - including those on the Cordova and Phonegap website.
NOTE YOUR APP IS NOW INSECURE. IT IS UP TO YOU TO SECURE YOUR APP.
Add the following to your index.html. Note, the star (*) which is missing in your file.
<meta http-equiv="Content-Security-Policy"
content="default-src *;
style-src * 'self' 'unsafe-inline' 'unsafe-eval';
script-src * 'self' 'unsafe-inline' 'unsafe-eval';">
You can also remove all Javascript from your index.html, it should have the same effect.
This whitelist worksheet should help with other parts.
HOW TO apply the Cordova/Phonegap the whitelist system
Make sure you also read the: whitelist matrix and the Whitelist CSP Examples
Best of Luck
I am new to Cordova. I have completed the installation process of Cordova 3.5.0 and hello World program is working fine for me. But when i am trying to use some Cordova API's like Alert it gives me the following error in logcat:
07-18 03:42:07.060: D/CordovaActivity(1183): onMessage(onPageStarted,file:///android_asset/www/index1.html)
07-18 03:42:08.170: D/CordovaWebViewClient(1183): onPageFinished(file:///android_asset/www/index1.html)
07-18 03:42:08.170: D/CordovaActivity(1183): onMessage(onPageFinished,file:///android_asset/www/index1.html)
07-18 03:42:08.410: D/CordovaActivity(1183): onMessage(spinner,stop)
07-18 03:42:10.180: D/CordovaActivity(1183): onMessage(spinner,stop)
07-18 03:42:12.740: D/CordovaLog(1183): file:///android_asset/www/index1.html: Line 28 : Uncaught TypeError: Cannot call method 'alert' of undefined
This is my HelloWorld.java
package com.example.hello;
import org.apache.cordova.CordovaActivity;
import android.os.Bundle;
public class HelloWorld extends CordovaActivity
{
#SuppressWarnings("deprecation")
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//super.init();
// Set by <content src="index.html" /> in config.xml
//super.loadUrl(Config.getStartUrl());
//super.loadUrl("file:///android_asset/www/index.html");
super.setIntegerProperty("splashscreen", R.drawable.splash);
super.loadUrl("file:///android_asset/www/index1.html", 5000);
}
}
And This is my index1.html:
<!DOCTYPE html>
<html>
<head>
<title>Notification Example</title>
<script type="text/javascript" charset="utf-8" src="cordova.js"></script>
<script type="text/javascript" charset="utf-8">
// Wait for device API libraries to load
//
document.addEventListener("deviceready", onDeviceReady, false);
// device APIs are available
//
function onDeviceReady() {
// Empty
}
// alert dialog dismissed
function alertDismissed() {
// do something
}
// Show a custom alertDismissed
//
function showAlert() {
navigator.notification.alert(
'You are the winner!', // message
alertDismissed, // callback
'Game Over', // title
'Done' // buttonName
);
}
</script>
</head>
<body>
<p>Show Alert</p>
</body>
</html>
My Manifest file:
<?xml version='1.0' encoding='utf-8'?>
<manifest android:hardwareAccelerated="true" android:versionCode="1" android:versionName="0.0.1" android:windowSoftInputMode="adjustPan" package="com.example.hello" 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.VIBRATE" />
<application android:hardwareAccelerated="true" android:icon="#drawable/icon" android:label="#string/app_name">
<activity android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale" android:label="#string/app_name" android:launchMode="singleTop" android:name="HelloWorld" android:theme="#android:style/Theme.Black.NoTitleBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="10" android:targetSdkVersion="19" />
</manifest>
my config.xml file:
<?xml version='1.0' encoding='utf-8'?>
<widget id="com.example.hello" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
<preference name="loglevel" value="DEBUG" />
<preference name="AndroidLaunchMode" value="singleTop" />
<feature name="App">
<param name="android-package" value="org.apache.cordova.App" />
</feature>
<feature name="Notification">
<param name="android-package" value="org.apache.cordova.Notification" />
</feature>
<name>HelloWorld</name>
<description>
A sample Apache Cordova application that responds to the deviceready event.
</description>
<author email="dev#cordova.apache.org" href="http://cordova.io">
Apache Cordova Team
</author>
<content src="index1.html" />
<access origin="*" />
</widget>
Please suggest how to resolve this issue.
You need to add dialogs plugin first.
You can add it using below command.
cordova plugin add org.apache.cordova.dialogs
I realize that similar questions have been asked but none of the solutions posted have worked for me, so maybe my situation is a bit different. I am using Phonegap and JQuery Mobile together. I have included cordova.js as per the instructions in my index.html:
<!doctype html>
<html>
<head>
<title>Convo</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="jquery_mobile/jquery.mobile-1.4.2.min.css" />
<link rel="stylesheet" href="owl/owl-carousel/owl.carousel.css">
<link rel="stylesheet" href="owl/owl-carousel/owl.theme.css">
<link rel="stylesheet" href="owl/home_slider.css">
<link rel="stylesheet" href="css/convo.min.css" />
<script src="jquery/jquery.js"></script>
<script src="owl/owl-carousel/owl.carousel.js"></script>
<script src="javascript/owl_effects.js"></script>
<script type="text/javascript" charset="utf-8" src="cordova.js"></script>
<script src="jquery_mobile/jquery.mobile-1.4.2.min.js"></script>
<script src="quickblox/quickblox.js"></script>
<script src="javascript/controller.js"></script>
</head>
<body>
<div data-role="page" id="home">
<div id="owl-demo" class="owl-carousel owl-theme">
<div class="item"><img src="images/space1.jpg" alt="The Last of us"></div>
<div class="item"><img src="images/space2.jpg" alt="GTA V"></div>
<div class="item"><img src="images/space3.jpg" alt="Mirror Edge"></div>
</div>
<div role="main" class="ui-content">
<label for="user_login">Email:</label>
<input type="email" name="name" id="user_login" data-clear-btn="true" value="">
<label for="user_password">Password:</label>
<input type="password" name="name" id="user_password" data-clear-btn="true" value="">
<input type="button" value="Sign In" onclick="home_signin_clicked()">
<input type="button" value="Join!" onclick="home_join_clicked()">
</div>
</div>
</body>
</html>
In an attached Javascript, I have a listener for the deviceready event. I am not sure if document.ready() is somehow interfering with it:
$(function()
{ //shorthand document.ready function
document_ready = true;
stored_view = localStorage.getItem("view");
if(!stored_view)
{
//home
change_view("home");
}
else if(stored_view != view)
{
//go to stored view
change_view(stored_view);
}
});
function device_is_ready()
{
phonegap_ready = true;
if(navigator.network.connection.type == Connection.NONE || navigator.network.connection.type == Connection.UNKNOWN)
{
online = false;
alert("offline");
}
else
{
online = true;
alert("online");
}
}
document.addEventListener("deviceready", device_is_ready, true);
So far, I've tried defining the function inside of the addEventListener, amd I've tried attaching the listener inside the document.ready(). Neither solution worked. The weird thing is that I have had this same set up for weeks and never had a problem. I should mention that I'm using Adobe build to make the APK (i'm using Android). Any ideas?
Edit: Here is my entire config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- config.xml reference: https://build.phonegap.com/docs/config-xml -->
<widget xmlns = "http://www.w3.org/ns/widgets"
xmlns:gap = "http://phonegap.com/ns/1.0"
id = "com.phonegap.hello-world"
version = "1.0.0">
<name>Convo</name>
<description>
App Prototype
</description>
<author href="http://phonegap.com" email="support#phonegap.com">
PhoneGap Team
</author>
<!--
If you do not want any permissions to be added to your app, add the
following tag to your config.xml; you will still have the INTERNET
permission on your app, which PhoneGap requires.
-->
<preference name="permissions" value="none"/>
<!-- Customize your app and platform with the preference element. -->
<preference name="phonegap-version" value="3.4.0" /> <!-- all: current version of PhoneGap -->
<preference name="orientation" value="default" /> <!-- all: default means both landscape and portrait are enabled -->
<preference name="target-device" value="universal" /> <!-- all: possible values handset, tablet, or universal -->
<preference name="fullscreen" value="false" /> <!-- all: hides the status bar at the top of the screen -->
<preference name="webviewbounce" value="true" /> <!-- ios: control whether the screen 'bounces' when scrolled beyond the top -->
<preference name="prerendered-icon" value="true" /> <!-- ios: if icon is prerendered, iOS will not apply it's gloss to the app's icon on the user's home screen -->
<preference name="stay-in-webview" value="false" /> <!-- ios: external links should open in the default browser, 'true' would use the webview the app lives in -->
<preference name="ios-statusbarstyle" value="black-opaque" /> <!-- ios: black-translucent will appear black because the PhoneGap webview doesn't go beneath the status bar -->
<preference name="detect-data-types" value="true" /> <!-- ios: controls whether data types (such as phone no. and dates) are automatically turned into links by the system -->
<preference name="exit-on-suspend" value="false" /> <!-- ios: if set to true, app will terminate when home button is pressed -->
<preference name="show-splash-screen-spinner" value="true" /> <!-- ios: if set to false, the spinner won't appear on the splash screen during app loading -->
<preference name="auto-hide-splash-screen" value="true" /> <!-- ios: if set to false, the splash screen must be hidden using a JavaScript API -->
<preference name="disable-cursor" value="false" /> <!-- blackberry: prevents a mouse-icon/cursor from being displayed on the app -->
<preference name="android-minSdkVersion" value="7" /> <!-- android: MIN SDK version supported on the target device. MAX version is blank by default. -->
<preference name="android-installLocation" value="auto" /> <!-- android: app install location. 'auto' will choose. 'internalOnly' is device memory. 'preferExternal' is SDCard. -->
<!-- Plugins -->
<!-- Core plugins -->
<gap:plugin name="org.apache.cordova.battery-status" />
<gap:plugin name="org.apache.cordova.camera" />
<gap:plugin name="org.apache.cordova.media-capture" />
<gap:plugin name="org.apache.cordova.console" />
<gap:plugin name="org.apache.cordova.contacts" />
<gap:plugin name="org.apache.cordova.device" />
<gap:plugin name="org.apache.cordova.device-motion" />
<gap:plugin name="org.apache.cordova.device-orientation" />
<gap:plugin name="org.apache.cordova.dialogs" />
<gap:plugin name="org.apache.cordova.file" />
<gap:plugin name="org.apache.cordova.file-transfer" />
<gap:plugin name="org.apache.cordova.geolocation" />
<gap:plugin name="org.apache.cordova.globalization" />
<gap:plugin name="org.apache.cordova.inappbrowser" />
<gap:plugin name="org.apache.cordova.media" />
<gap:plugin name="org.apache.cordova.network-information" />
<gap:plugin name="org.apache.cordova.splashscreen" />
<gap:plugin name="org.apache.cordova.vibration" />
<!-- Third party plugins -->
<!-- A list of available plugins are available at https://build.phonegap.com/plugins -->
<!--
<gap:plugin name="com.phonegap.plugins.barcodescanner" />
-->
<!-- Define app icon for each platform. This is a relative path to config.xml.
For e.g. if you place an icon.png inside res folder, you should modify the
src in the following setting to "res/icon.png" -->
<icon src="icon.png" />
<icon src="res/icon/android/icon-36-ldpi.png" gap:platform="android" gap:qualifier="ldpi" />
<icon src="res/icon/android/icon-48-mdpi.png" gap:platform="android" gap:qualifier="mdpi" />
<icon src="res/icon/android/icon-72-hdpi.png" gap:platform="android" gap:qualifier="hdpi" />
<icon src="res/icon/android/icon-96-xhdpi.png" gap:platform="android" gap:qualifier="xhdpi" />
<icon src="res/icon/blackberry/icon-80.png" gap:platform="blackberry" />
<icon src="res/icon/blackberry/icon-80.png" gap:platform="blackberry" gap:state="hover"/>
<icon src="res/icon/ios/icon-57.png" gap:platform="ios" width="57" height="57" />
<icon src="res/icon/ios/icon-72.png" gap:platform="ios" width="72" height="72" />
<icon src="res/icon/ios/icon-57-2x.png" gap:platform="ios" width="114" height="114" />
<icon src="res/icon/ios/icon-72-2x.png" gap:platform="ios" width="144" height="144" />
<icon src="res/icon/webos/icon-64.png" gap:platform="webos" />
<icon src="res/icon/windows-phone/icon-48.png" gap:platform="winphone" />
<icon src="res/icon/windows-phone/icon-173.png" gap:platform="winphone" gap:role="background" />
<!-- Define app splash screen for each platform. -->
<gap:splash src="res/screen/android/screen-ldpi-portrait.png" gap:platform="android" gap:qualifier="port-ldpi" />
<gap:splash src="res/screen/android/screen-mdpi-portrait.png" gap:platform="android" gap:qualifier="port-mdpi" />
<gap:splash src="res/screen/android/screen-hdpi-portrait.png" gap:platform="android" gap:qualifier="port-hdpi" />
<gap:splash src="res/screen/android/screen-xhdpi-portrait.png" gap:platform="android" gap:qualifier="port-xhdpi" />
<gap:splash src="res/screen/blackberry/screen-225.png" gap:platform="blackberry" />
<gap:splash src="res/screen/ios/screen-iphone-portrait.png" gap:platform="ios" width="320" height="480" />
<gap:splash src="res/screen/ios/screen-iphone-portrait-2x.png" gap:platform="ios" width="640" height="960" />
<gap:splash src="res/screen/ios/screen-iphone-portrait-568h-2x.png" gap:platform="ios" width="640" height="1136" />
<gap:splash src="res/screen/ios/screen-ipad-portrait.png" gap:platform="ios" width="768" height="1024" />
<gap:splash src="res/screen/ios/screen-ipad-landscape.png" gap:platform="ios" width="1024" height="768" />
<gap:splash src="res/screen/windows-phone/screen-portrait.jpg" gap:platform="winphone" />
<!--
Define access to external domains.
<access /> - a blank access tag denies access to all external resources.
<access origin="*" /> - a wildcard access tag allows access to all external resource.
Otherwise, you can specify specific domains:
-->
<access origin="*"/>
<!--
<access origin="http://phonegap.com" /> - allow any secure requests to http://phonegap.com/
<access origin="http://phonegap.com" subdomains="true" /> - same as above, but including subdomains, such as http://build.phonegap.com/
<access origin="http://phonegap.com" browserOnly="true" /> - only allows http://phonegap.com to be opened by the child browser.
-->
</widget>
In script, change:
document.addEventListener("deviceready", device_is_ready, false);
In config.xml, Add this :
<gap:plugin name="org.apache.cordova.device" />
Also, please keep the deviceready method, only in index.html
I have zero experience with mobile applications, but the company I work for is developing an application that we want to be able to port to both iOS and Android without too much overhead involved. Thus, we decided to use PhoneGap.
I still know very little about it. I learn by practicing, and what I'm trying to do is get the basics set up so that I can start doing my own thing, building, testing, and adding onto the project.
I currently have it synced with Adobe Build. I am able to execute the "phonegap run android" command and then rebuild it on AB. Then, I use a barcode scanner app on my Android tablet to get the link to the download, after which I can test it out.
My Question:
I am trying to set up a simple application to test out the Compass plugin. I am using this tutorial from the PhoneGap blog that I found here:
http://docs.phonegap.com/en/2.1.0/cordova_compass_compass.md.html
There is a section where they give a "Full Example", with the following code:
<!DOCTYPE html>
<html>
<head>
<title>Compass Example</title>
<script type="text/javascript" charset="utf-8" src="cordova-2.1.0.js"></script>
<script type="text/javascript" charset="utf-8">
// The watch id references the current `watchHeading`
var watchID = null;
// Wait for Cordova to load
//
document.addEventListener("deviceready", onDeviceReady, false);
// Cordova is ready
//
function onDeviceReady() {
startWatch();
}
// Start watching the compass
//
function startWatch() {
// Update compass every 3 seconds
var options = { frequency: 3000 };
watchID = navigator.compass.watchHeading(onSuccess, onError, options);
}
// Stop watching the compass
//
function stopWatch() {
if (watchID) {
navigator.compass.clearWatch(watchID);
watchID = null;
}
}
// onSuccess: Get the current heading
//
function onSuccess(heading) {
var element = document.getElementById('heading');
element.innerHTML = 'Heading: ' + heading.magneticHeading;
}
// onError: Failed to get the heading
//
function onError(compassError) {
alert('Compass error: ' + compassError.code);
}
</script>
</head>
<body>
<div id="heading">Waiting for heading...</div>
<button onclick="startWatch();">Start Watching</button>
<button onclick="stopWatch();">Stop Watching</button>
</body>
</html>
The project that was created via the "phonegap create my-app" gave me a familiar environment with folders for CSS, JS, images, and some other folders which I am unfamiliar with.
When I built the contents of the folder I was able to successfully see the blinking "PhoneGap Ready" bar, so it appears that Cordova is working correctly.
I replaced the index.html file with the code above. When I built and ran the app, I saw the PhoneGap logo, then that disappeared and the application started. I see some text that says "Waiting for heading...", as well as two buttons: (1) Start Watching and (2) Stop Watching.
Nothing happens when I click the buttons. I know this question is really niche, so if I have been unable to provide specific enough details to determine the solution, then I would really appreciate an explanation on how plugins are supposed to work.
Do I need to include a line of code specific to Android or iOS that tells the device that I want access to the Compass? Do you know of any examples of working projects that I could try to load myself?
Thanks,
Joe Majewski
Update:
As per a request, here is my config.xml file:
<?xml version='1.0' encoding='utf-8'?>
<widget id="com.phonegap.helloworld" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:gap="http://phonegap.com/ns/1.0">
<name>HelloWorld</name>
<description>
Hello World sample application that responds to the deviceready event.
</description>
<author email="support#phonegap.com" href="http://phonegap.com">
PhoneGap Team
</author>
<feature name="http://api.phonegap.com/1.0/device" />
<preference name="permissions" value="none" />
<preference name="orientation" value="default" />
<preference name="target-device" value="universal" />
<preference name="fullscreen" value="true" />
<preference name="webviewbounce" value="true" />
<preference name="prerendered-icon" value="true" />
<preference name="stay-in-webview" value="false" />
<preference name="ios-statusbarstyle" value="black-opaque" />
<preference name="detect-data-types" value="true" />
<preference name="exit-on-suspend" value="false" />
<preference name="show-splash-screen-spinner" value="true" />
<preference name="auto-hide-splash-screen" value="true" />
<preference name="disable-cursor" value="false" />
<preference name="android-minSdkVersion" value="7" />
<preference name="android-installLocation" value="auto" />
<icon src="icon.png" />
<icon gap:density="ldpi" gap:platform="android" src="res/icon/android/icon-36-ldpi.png" />
<icon gap:density="mdpi" gap:platform="android" src="res/icon/android/icon-48-mdpi.png" />
<icon gap:density="hdpi" gap:platform="android" src="res/icon/android/icon-72-hdpi.png" />
<icon gap:density="xhdpi" gap:platform="android" src="res/icon/android/icon-96-xhdpi.png" />
<icon gap:platform="blackberry" src="res/icon/blackberry/icon-80.png" />
<icon gap:platform="blackberry" gap:state="hover" src="res/icon/blackberry/icon-80.png" />
<icon gap:platform="ios" height="57" src="res/icon/ios/icon-57.png" width="57" />
<icon gap:platform="ios" height="72" src="res/icon/ios/icon-72.png" width="72" />
<icon gap:platform="ios" height="114" src="res/icon/ios/icon-57-2x.png" width="114" />
<icon gap:platform="ios" height="144" src="res/icon/ios/icon-72-2x.png" width="144" />
<icon gap:platform="webos" src="res/icon/webos/icon-64.png" />
<icon gap:platform="winphone" src="res/icon/windows-phone/icon-48.png" />
<icon gap:platform="winphone" gap:role="background" src="res/icon/windows-phone/icon-173.png" />
<gap:splash gap:density="ldpi" gap:platform="android" src="res/screen/android/screen-ldpi-portrait.png" />
<gap:splash gap:density="mdpi" gap:platform="android" src="res/screen/android/screen-mdpi-portrait.png" />
<gap:splash gap:density="hdpi" gap:platform="android" src="res/screen/android/screen-hdpi-portrait.png" />
<gap:splash gap:density="xhdpi" gap:platform="android" src="res/screen/android/screen-xhdpi-portrait.png" />
<gap:splash gap:platform="blackberry" src="res/screen/blackberry/screen-225.png" />
<gap:splash gap:platform="ios" height="480" src="res/screen/ios/screen-iphone-portrait.png" width="320" />
<gap:splash gap:platform="ios" height="960" src="res/screen/ios/screen-iphone-portrait-2x.png" width="640" />
<gap:splash gap:platform="ios" height="1024" src="res/screen/ios/screen-ipad-portrait.png" width="768" />
<gap:splash gap:platform="ios" height="768" src="res/screen/ios/screen-ipad-landscape.png" width="1024" />
<gap:splash gap:platform="winphone" src="res/screen/windows-phone/screen-portrait.jpg" />
<access origin="http://127.0.0.1*" />
</widget>
May you post your AndroidManifest.xml and config.xml files?
They should look like this:
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="us.custom4.calculodecuadro"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="15" />
<supports-screens
android:largeScreens="true"
android:normalScreens="true"
android:smallScreens="true"
android:resizeable="true"
android:anyDensity="true" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale"
android:name=".MainActivity"
android:label="#string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
config.xml
<cordova>
<plugin name="Geolocation" value="org.apache.cordova.GeoBroker" />
<plugin name="File" value="org.apache.cordova.FileUtils" />
<plugin name="FileTransfer" value="org.apache.cordova.FileTransfer" />
<plugin name="Notification" value="org.apache.cordova.Notification"/>
<plugin name="Storage" value="org.apache.cordova.Storage" />
<plugin name="Battery" value="org.apache.cordova.BatteryListener" />
<plugin name="Device" value="org.apache.cordova.Device" />
<access origin="http://127.0.0.1*"/>
<access origin=".*"/>
<log level="DEBUG"/>
<preference name="useBrowserHistory" value="false" />
<preference name="exit-on-suspend" value="false" />
<plugins>
<plugin name="App" value="org.apache.cordova.App"/>
<plugin name="Geolocation" value="org.apache.cordova.GeoBroker"/>
<plugin name="Device" value="org.apache.cordova.Device"/>
<plugin name="Accelerometer" value="org.apache.cordova.AccelListener"/>
<plugin name="Compass" value="org.apache.cordova.CompassListener"/>
<plugin name="Media" value="org.apache.cordova.AudioHandler"/>
<plugin name="Camera" value="org.apache.cordova.CameraLauncher"/>
<plugin name="Contacts" value="org.apache.cordova.ContactManager"/>
<plugin name="File" value="org.apache.cordova.FileUtils"/>
<plugin name="NetworkStatus" value="org.apache.cordova.NetworkManager"/>
<plugin name="Notification" value="org.apache.cordova.Notification"/>
<plugin name="Storage" value="org.apache.cordova.Storage"/>
<plugin name="Temperature" value="org.apache.cordova.TempListener"/>
<plugin name="FileTransfer" value="org.apache.cordova.FileTransfer"/>
<plugin name="Capture" value="org.apache.cordova.Capture"/>
<plugin name="Battery" value="org.apache.cordova.BatteryListener"/>
<plugin name="SplashScreen" value="org.apache.cordova.SplashScreen"/>
<plugin name="Echo" value="org.apache.cordova.Echo" />
</plugins>