PhoneGap:Buildをモバイルバージョン用に使用するWebアプリケーションを開発しており、「デスクトップ」およびモバイルバージョン用の単一のコードベースが必要です。 PhoneGap呼び出しが機能するかどうかを検出できるようにしたい(つまり、PhoneGapをサポートするモバイルデバイスのユーザー)。
私は検索しましたが、これを行う簡単な方法はありません。多くの人が提案を提供しています。
PhoneGap Javascriptファイルをデスクトップバージョンのアプリから削除しない限り、どれも機能しません。これは、1つのコードベースを持つという私の目標に反します。
これまでに私が思いついた唯一の解決策は、ブラウザ/ユーザーエージェントのスニッフィングですが、これは控えめに言っても堅牢ではありません。より良いソリューションは大歓迎です!
編集:やや良い解決策は、いくつかの小さなタイムアウト後にPhoneGap関数を呼び出すことです-それが機能しない場合は、ユーザーがデスクトップWebブラウザを使用していると仮定します。
私はこのコードを使用します:
if (navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry|IEMobile)/)) {
document.addEventListener("deviceready", onDeviceReady, false);
} else {
onDeviceReady(); //this is the browser
}
更新
Phonegapがブラウザで実行されているかどうかを検出する方法は他にもたくさんありますが、ここにもう1つの素晴らしいオプションがあります。
var app = document.URL.indexOf( 'http://' ) === -1 && document.URL.indexOf( 'https://' ) === -1;
if ( app ) {
// PhoneGap application
} else {
// Web page
}
ここに見られるように: モバイルブラウザかPhoneGapアプリケーションの間で検出
数日前に post について書いた。これはあなたが見つけることができる最良のソリューションです(PhoneGapが何かをリリースするまで、多分そうでないかもしれません)、それは短く、シンプルで完璧です(あらゆる可能な方法とプラットフォームでチェックしました)。
この関数は、ケースの98%でジョブを実行します。
/**
* Determine whether the file loaded from PhoneGap or not
*/
function isPhoneGap() {
return (window.cordova || window.PhoneGap || window.phonegap)
&& /^file:\/{3}[^\/]/i.test(window.location.href)
&& /ios|iphone|iPod|ipad|Android/i.test(navigator.userAgent);
}
if ( isPhoneGap() ) {
alert("Running on PhoneGap!");
} else {
alert("Not running on PhoneGap!");
}
他の2%のケースを完了するには、次の手順を実行します(ネイティブコードにわずかな変更が必要です)。
ソースを使用して、__ phonegap_index.htmlというファイルを作成します。
<!-- __phonegap_index.html -->
<script type="text/javascript">
function isPhoneGap() {
//the function's content is as described above
}
//ensure the 98% that this file is called from PhoneGap.
//in case somebody accessed this file directly from the browser.
if ( isPhoneGap() )
localStorage.setItem("isPhoneGap","1");
//and redirect to the main site file.
window.location = "index.html";
</script>
さて、ネイティブでは、開始ページをindex.htmlから__ phonegap_index.htmlすべてのPhoneGapプラットフォームで。私のプロジェクト名がexampleで、変更する必要があるファイルが(PhoneGapバージョン2.2.0に関して)であるとしましょう:
CordovaLibApp/AppDelegate.m
src/org/Apache/cordova/example/cordovaExample.Java
example/package.appxmanifest
www/config.xml
framework/appinfo.json
src/WebForm.cpp
(56行目)最後に、PhoneGapで実行されているかどうかにかかわらず、サイトのどこでも使用できます。
if ( localStorage.getItem("isPhoneGap") ) {
alert("Running on PhoneGap!");
} else {
alert("Not running on PhoneGap!");
}
それが役に立てば幸い。 :-)
しばらく前に回答されていましたが、「PhoneGap.available」はもう存在しません。以下を使用する必要があります。
if (window.PhoneGap) {
//do stuff
}
または1.7以降、好む:
if (window.cordova) {
//do stuff
}
EDIT 2019:コメントで述べたように、これは、デスクトップブラウザービルドにcordova libを含めない場合にのみ機能します。そしてもちろん、ターゲットとするデバイスごとに最小限のjavascript/html/cssファイルのみを含めることをお勧めします
Cordova/phonegapアプリケーションにいるかどうかを判断する最も信頼できる方法は、この構成 AppendUserAgent を使用してcordovaアプリケーションのユーザーエージェントを変更することです。
config.xml
に追加:
<preference name="AppendUserAgent" value="Cordova" />
次に呼び出します:
var isCordova = navigator.userAgent.match(/Cordova/i))
どうして?
window.cordova
およびdocument.addEventListener('deviceready', function(){});
はレース条件の対象ですnavigator.standalone
がWebサイトの場合、<content src="index.html" />
は機能しません(例:<content src="https://www.example.com/index.html" />
または cordova-plugin-remote-injection )これは最も簡単だと思う:var isPhoneGap = (location.protocol == "file:")
EDIT動作しなかった一部の人々。その後、試してみてください(テストしていない)
var isPhoneGap = ! /^http/.test(location.protocol);
これは私のために動作します(1.7.0を実行)
if (window.device) {
// Running on PhoneGap
}
デスクトップChromeおよびSafariでテスト済み。
元のポスターのように、phonegapビルドサービスを使用しています。 2日間と約50のテストビルドの後、私は自分に最適なエレガントなソリューションを思いつきました。
モバイルブラウザでテストして実行したかったため、UAスニッフィングを使用できませんでした。私はもともとcobberboyの非常に機能的なテクニックに落ち着いていました。 「howPatientAreWe:10000」の遅延/タイムアウトは、ブラウザー内の開発にとって厄介なものだったため、これはうまくいきませんでした。また、それより低い値に設定すると、アプリ/デバイスモードでのテストに失敗する場合があります。別の方法が必要でした...
Phonegapビルドサービスでは、アプリのファイルをサービスに送信する前に、コードリポジトリからphonegap.js
ファイルを省略する必要があります。したがって、ブラウザとアプリのどちらで実行されているかを判断するために、その存在をテストできます。
もう1つの注意点として、jQueryMobileも使用しているため、カスタムスクリプトを開始する前にjQMとphonegapの両方を初期化する必要がありました。次のコードは、アプリのカスタムindex.jsファイルの先頭に配置されます(jQueryの後、jQMの前)。また、phonegapビルドドキュメントは、HTMLのどこかに<script src="phonegap.js"></script>
を配置するよう指示しています。完全に省き、$。getScript()を使用してロードして、その存在をテストします。
isPhoneGap = false;
isPhoneGapReady = false;
isjQMReady = false;
$.getScript("phonegap.js")
.done(function () {
isPhoneGap = true;
document.addEventListener("deviceready", function () {
console.log("phonegap ready - device/app mode");
isPhoneGapReady = true;
Application.checkReadyState();
}, false);
})
.fail(function () {
console.log("phonegap load failed - browser only");
isPhoneGapReady = true;
Application.checkReadyState();
});
$(document).bind("mobileinit", function () {
Application.mobileInit();
$(document).one("pageinit", "#Your_First_jQM_Page", function () {
isjQMReady = true;
Application.checkReadyState();
});
});
Application = {
checkReadyState: function () {
if (isjQMReady && isPhoneGapReady) {
Application.ready();
}
},
mobileInit: function () {
// jQM initialization settings go here
// i.e. $.mobile.defaultPageTransition = 'slide';
},
ready: function () {
// Both phonegap (if available) and jQM are fired up and ready
// let the custom scripting begin!
}
}
興味深いことに、多くの回答がありますが、これらの3つのオプションは含まれていません。
1 – cordova.jsは、グローバルスコープでcordovaオブジェクトを設定します。存在する場合、おそらくCordovaスコープで実行されています。
var isCordovaApp = !!window.cordova;
2 – Cordovaは、デスクトップからHTMLドキュメントを開くようにアプリケーションを実行します。 HTTPプロトコルの代わりに、FILEを使用します。これを検出すると、アプリがローカルにロードされたと推測する機会が得られます。
var isCordovaApp = document.URL.indexOf('http://') === -1
&& document.URL.indexOf('https://') === -1;
3 – cordovaスクリプトのloadイベントを使用して、コンテキストを検出します。スクリプトインクルードはビルドプロセスで簡単に削除できます。そうしないと、ブラウザーでスクリプトの読み込みが失敗します。そのため、このグローバル変数は設定されません。
<script src="../cordova.js" onload="javascript:window.isCordovaApp = true;"></script>
クレジットは AdobeのDamien Antipa
私はこの方法を使用します:
debug = (window.cordova === undefined);
debug
は、ブラウザ環境ではtrue
になり、デバイスではfalse
になります。
これは実行可能であるようであり、本番環境で使用しました。
if (document.location.protocol == "file:") {
// file protocol indicates phonegap
document.addEventListener("deviceready", function() { $(initInternal);} , false);
}
else {
// no phonegap, start initialisation immediately
$(initInternal);
}
ソース: http://tqcblog.com/2012/05/09/detecting-phonegap-cordova-on-startup/
問題の本質は、cordova.deviceが未定義である限り、コードが、デバイスがサポートされていないことをCordovaが確立したためか、またはCordovaがまだ準備中であって後でデバイスが起動するためかどうかを確認できないことです(または3番目のオプション:cordovaが正しく読み込まれませんでした)。
唯一の解決策は、待機期間を定義し、この期間の後、コードがデバイスがサポートされていないと想定する必要があることを決定することです。 Cordovaが「サポートされているデバイスを見つけようと試みましたが、あきらめました」というパラメータをどこかに設定してほしいのですが、そのようなパラメータはないようです。
これが確立されたら、サポートされているデバイスがない状況で具体的に何かを行うことができます。私の場合、デバイスのアプリ市場へのリンクを隠すようなものです。
ほとんどすべての状況をカバーするこの関数をつなぎ合わせました。 devicereadyハンドラー、device-never-readyハンドラー、および待機時間を定義できます。
//Deals with the possibility that the code will run on a non-phoneGap supported
//device such as desktop browsers. Gives several options including waiting a while
//for cordova to load after all.
//In:
//onceReady (function) - performed as soon as deviceready fires
//patience
// (int) - time to wait before establishing that cordova will never load
// (boolean false) - don't wait: assume that deviceready will never fire
//neverReady
// (function) - performed once it's established deviceready will never fire
// (boolean true) - if deviceready will never fire, run onceReady anyhow
// (boolean false or undefined) - if deviceready will never fire, do nothing
function deviceReadyOrNot(onceReady,patience,neverReady){
if (!window.cordova){
console.log('Cordova was not loaded when it should have been')
if (typeof neverReady == "function"){neverReady();}
//If phoneGap script loaded...
} else {
//And device is ready by now...
if (cordova.device){
callback();
//...or it's loaded but device is not ready
} else {
//...we might run the callback after
if (typeof patience == "number"){
//Run the callback as soon as deviceready fires
document.addEventListener('deviceready.patience',function(){
if (typeof onceReady == "function"){onceReady();}
})
//Set a timeout to disable the listener
window.setTimeout(function(){
//If patience has run out, unbind the handler
$(document).unbind('deviceready.patience');
//If desired, manually run the callback right now
if (typeof neverReady == 'function'){neverReady();}
},patience);
//...or we might just do nothing
} else {
//Don't bind a deviceready handler: assume it will never happen
if (typeof neverReady == 'function'){neverReady();}
else if (neverReady === true){onceReady();}
else {
//Do nothing
}
}
}
}
}
SlavikMeのソリューションに基づく別の方法:
PhoneGapソースからindex.html
に渡されるクエリパラメーターを使用するだけです。つまり、Androidではなく
super.loadUrl("file:///Android_asset/www/index.html");
つかいます
super.loadUrl("file:///Android_asset/www/index.html?phonegap=1");
SlavikMeには、他のプラットフォームでこれを行う場所に関するすばらしいリストがあります。
その後、index.html
は簡単にこれを行うことができます。
if (window.location.href.match(/phonegap=1/)) {
alert("phonegap");
}
else {
alert("not phonegap");
}
私がそれをやっている方法は、ブラウザ専用バージョンのcordova.jsによって上書きされるグローバル変数を使用することです。メインhtmlファイル(通常index.html
)には、順序に依存する次のスクリプトがあります。
<script>
var __cordovaRunningOnBrowser__ = false
</script>
<script src="cordova.js"></script> <!-- must be included after __cordovaRunningOnBrowser__ is initialized -->
<script src="index.js"></script> <!-- must be included after cordova.js so that __cordovaRunningOnBrowser__ is set correctly -->
そしてcordova.js
の中に私は単純に:
__cordovaRunningOnBrowser__ = true
モバイルデバイス用にビルドする場合、cordova.jsは使用されません(代わりにプラットフォーム固有のcordova.jsファイルが使用されます)。したがって、この方法には、プロトコル、userAgent、またはライブラリに関係なく100%正しいという利点があります。変数(変更される場合があります)。 cordova.jsに含める必要のあるものは他にもあるかもしれませんが、それらが何であるかはまだわかりません。
1つのコードベースを維持するには、コードが実行されている「プラットフォーム」が重要です。私にとって、この「プラットフォーム」には3つの異なるものがあります。
プラットフォームを確認する方法:
var platform;
try {
cordova.exec(function (param) {
platform = 2;
}, function (err) {}, "Echo", "echo", ["test"]);
} catch (e) {
platform = 'ontouchstart' in document.documentElement ? 1 : 0;
}
注意:
これはcordova.jsがロードされた後にのみ実行(body onload(...)、$(document).ready(...))でなければなりません
document.documentElementの 'ontouchstart'は、タッチ対応画面を備えたラップトップおよびデスクトップモニターに存在するため、デスクトップであってもモバイルブラウザーを報告します。より正確なチェックを行うにはさまざまな方法がありますが、必要なケースの99%を引き続き処理するため、それを使用します。その行を、より堅牢なものにいつでも置き換えることができます。
本当に質問への回答ではありませんが、デスクトップブラウザーでテストするときは、localstorage値を設定するだけで、ブラウザーがアプリをロードして、デバイスが起動しないようになります。
function main() {
// Initiating the app here.
};
/* Listen for ready events from pheongap */
document.addEventListener("deviceready", main, false);
// When testing outside ipad app, use jquerys ready event instead.
$(function() {
if (localStorage["notPhonegap"]) {
main();
}
});
同じ問題があります。
CordovaクライアントによってロードされたURLに#cordova = trueを追加し、Webページでlocation.hash.indexOf( "cordova = true")> -1をテストします。
以下は、最新のPhoneGap/Cordova(2.1.0)で動作します。
使い方:
利点:
短所:
==
真新しい空のPhoneGapプロジェクトを作成します。提供されているサンプルのindex.jsでは、下部の「app」変数を次のように置き換えます。
var app = {
// denotes whether we are within a mobile device (otherwise we're in a browser)
iAmPhoneGap: false,
// how long should we wait for PhoneGap to say the device is ready.
howPatientAreWe: 10000,
// id of the 'too_impatient' timeout
timeoutID: null,
// id of the 'impatience_remaining' interval reporting.
impatienceProgressIntervalID: null,
// Application Constructor
initialize: function() {
this.bindEvents();
},
// Bind Event Listeners
//
// Bind any events that are required on startup. Common events are:
// `load`, `deviceready`, `offline`, and `online`.
bindEvents: function() {
document.addEventListener('deviceready', this.onDeviceReady, false);
// after 10 seconds, if we still think we're NOT phonegap, give up.
app.timeoutID = window.setTimeout(function(appReference) {
if (!app.iAmPhoneGap) // jeepers, this has taken too long.
// manually trigger (fudge) the receivedEvent() method.
appReference.receivedEvent('too_impatient');
}, howPatientAreWe, this);
// keep us updated on the console about how much longer to wait.
app.impatienceProgressIntervalID = window.setInterval(function areWeThereYet() {
if (typeof areWeThereYet.howLongLeft == "undefined") {
areWeThereYet.howLongLeft = app.howPatientAreWe; // create a static variable
}
areWeThereYet.howLongLeft -= 1000; // not so much longer to wait.
console.log("areWeThereYet: Will give PhoneGap another " + areWeThereYet.howLongLeft + "ms");
}, 1000);
},
// deviceready Event Handler
//
// The scope of `this` is the event. In order to call the `receivedEvent`
// function, we must explicity call `app.receivedEvent(...);`
onDeviceReady: function() {
app.iAmPhoneGap = true; // We have a device.
app.receivedEvent('deviceready');
// clear the 'too_impatient' timeout .
window.clearTimeout(app.timeoutID);
},
// Update DOM on a Received Event
receivedEvent: function(id) {
// clear the "areWeThereYet" reporting.
window.clearInterval(app.impatienceProgressIntervalID);
console.log('Received Event: ' + id);
myCustomJS(app.iAmPhoneGap); // run my application.
}
};
app.initialize();
function myCustomJS(trueIfIAmPhoneGap) {
// put your custom javascript here.
alert("I am "+ (trueIfIAmPhoneGap?"PhoneGap":"a Browser"));
}
アーロン、試してみて
if (PhoneGap.available){
do PhoneGap stuff;
}
数か月前にアプリを開始したときにこの問題に出くわしました。アプリを「browser-compatible
」にしたかったためです(そのシナリオでは、音声録音、コンパスなどの機能がブロックされることを理解しています) 。)。
アプリの実行コンテキストを事前に決定する唯一の100%
(および100%の条件を主張する)ソリューションは次のとおりです。
jS "flag"変数をtrueに初期化し、すべてのWebコンテキストでfalseに変更します。
したがって、「willIBeInPhoneGapSometimesInTheNearFuture()
」のような呼び出しを使用できます(これはPRE-PGです。もちろん、PG APIを呼び出すことができるかどうかを確認するPOST-PGメソッドが必要ですが、それは簡単です)。
次に、「but how do you determine the execution context
?」と言います。答えは「あなたはしない」(PGの優秀な人々がAPIコードでそれをしない限り、確実にできるとは思わないからです)。
1つのコードベースと2つのバリアントを備えたビルドスクリプトを作成します。
PhoneGap Javascriptファイルをデスクトップバージョンのアプリから削除しない限り、どれも機能しません。これは、1つのコードベースを持つという私の目標に反します。
別のオプションはmerges folderを使用することです。下のスクリーンショットを参照してください。
プラットフォーム固有のファイルを追加したり、デフォルトのファイルを上書きしたりできます。
(いくつかのシナリオでトリックを行う必要があります)
言い換えると、ブラウザを検出するのではなく、デスクトップビルド用の特定のファイルを含めず、iOS専用の特定のファイルを添付するだけです。
WindowsおよびMacマシンで動作します。 Linuxのソリューションを見つける必要がある 詳細を表示
var mobileDevice = false;
if(navigator.userAgent.match(/iPhone|iPad|iPod|Android|BlackBerry|IEMobile/))
mobileDevice = true;
if(mobileDevice && navigator.platform.match(/Win|Mac/i))
mobileDevice = false; // This is desktop browser emulator
if(mobileDevice) {
// include cordova files
}
GeorgeWのソリューションは問題ありませんが、実際のデバイスでもPhoneGap.availableは、PhoneGapのものが読み込まれた後にのみtrueになります。 document.addEventListener( 'deviceready'、onDeviceReady、false)のonDeviceReadyが呼び出されました。
その前に、知りたい場合は、次のようにすることができます:
runningInPcBrowser =
navigator.userAgent.indexOf('Chrome') >= 0 ||
navigator.userAgent.indexOf('Firefox') >= 0
このソリューションでは、ほとんどの開発者がChromeまたはFirefoxを使用して開発することを想定しています。
私はウィンドウオブジェクトを試していましたが、InAppBrowserでリモートURLを開いていたので機能しませんでした。できませんでした。そのため、それを実現するための最良かつ最も簡単な方法は、phonegapアプリから開く必要があるURLに文字列を追加することでした。次に、ドキュメントの場所に文字列が追加されているかどうかを確認します。
以下は簡単なコードです
var ref = window.open('http://yourdomain.org#phonegap', '_blank', 'location=yes');
URL「#phonegap」に文字列が追加されていることがわかります。したがって、ドメインURLに次のスクリプトを追加します。
if(window.location.indexOf("#phonegap") > -1){
alert("Url Loaded in the phonegap App");
}
PhoneGap 3.xモバイルアプリケーション開発Hotshot
var userLocale = "en-US";
function startApp()
{
// do translations, format numbers, etc.
}
function getLocaleAndStartApp()
{
navigator.globalization.getLocaleName (
function (locale) {
userLocale = locale.value;
startApp();
},
function () {
// error; start app anyway
startApp();
});
}
function executeWhenReady ( callback ) {
var executed = false;
document.addEventListener ( "deviceready", function () {
if (!executed) {
executed = true;
if (typeof callback === "function") {
callback();
}
}
}, false);
setTimeout ( function () {
if (!executed) {
executed = true;
if (typeof callback === "function") {
callback();
}
}
}, 1000 );
};
executeWhenReady ( function() {
getLocaleAndStartApp();
} );
およびYASMFフレームワークで
https://github.com/photokandyStudios/YASMF-Next/blob/master/lib/yasmf/util/core.js#L152
実際に、ここにリストした2つの手法の組み合わせが最も効果的であることがわかりました。まず、コルドバ/電話ギャップにアクセスできるかどうか、またデバイスが使用可能かどうかを確認します。そのようです:
function _initialize() {
//do stuff
}
if (window.cordova && window.device) {
document.addEventListener('deviceready', function () {
_initialize();
}, false);
} else {
_initialize();
}
if ( "device" in window ) {
// phonegap
} else {
// browser
}
このアプローチを試してください:
/**
* Returns true if the application is running on an actual mobile device.
*/
function isOnDevice(){
return navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry)/);
}
function isDeviceiOS(){
return navigator.userAgent.match(/(iPhone)/);
}
/**
* Method for invoking functions once the DOM and the device are ready. This is
* a replacement function for the JQuery provided method i.e.
* $(document).ready(...).
*/
function invokeOnReady(callback){
$(document).ready(function(){
if (isOnDevice()) {
document.addEventListener("deviceready", callback, false);
} else {
invoke(callback);
}
});
}
if (document.URL.includes('http')) {
// running in browser
}
Httpとhttpsの両方を処理します。
わずかに変更されましたが、問題なく完全に機能します。
Cordovaを読み込むのはデスクトップではなく組み込みデバイスの場合のみであるため、デスクトップブラウザーではCordovaを完全に回避します。 UIとMVVMのテストと開発は非常に快適です。
このコードを入れてください。ファイル内cordovaLoader.js
function isEmbedded() {
return
// maybe you can test for better conditions
//&& /^file:\/{3}[^\/]/i.test(window.location.href) &&
/ios|iphone|iPod|ipad|Android/i.test(navigator.userAgent);
}
if ( isEmbedded() )
{
var head= document.getElementsByTagName('head')[0];
var script= document.createElement('script');
script.type= 'text/javascript';
script.src= 'cordova-2.7.0.js';
head.appendChild(script);
}
次に、cordova javascript自体を含める代わりに、cordovaLoader.jsを含めます
<head>
<script src="js/cordovaLoader.js"></script>
<script src="js/jquery.js"></script>
<script src="js/iscroll.js"></script>
<script src="js/knockout-2.3.0.js"></script>
</head>
あなたの仕事を楽にします! :)
GeorgeW と mkprogramming の提案を組み合わせて使用します。
if (!navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry)/)) {
onDeviceReady();
} else if (Phonegap.available){
onDeviceReady();
} else {
console.log('There was an error loading Phonegap.')
}
どういうわけか彼らはそれほど違いはないのでしょうか?ハハ...面白くない。誰もこれが問題にならないとは思わなかったのですか?考慮事項の最も簡単なソリューションを次に示します。さまざまなファイルをサーバーにプッシュしてから、PhoneGapを実行します。また、一時的にhttp:チェックを使用することも推奨します。
var isMobileBrowserAndNotPhoneGap = (document.location.protocol == "http:");
私の興味はブラウザのナビゲーションバーを押し上げることにあるので、本当に隔離されたスクリプトのタグを削除し、[DWで]再構築を押すことができます(とにかく展開のためのクリーンアップがありますので、これはそれらのタスクの1つになります) PGにプッシュするときにisMobileBrowserAndNotPhoneGapを使用して手動で効率的にコメントアウトすることは、(他にあまり利用できないと考えて)良いオプションです。繰り返しになりますが、私の状況では、モバイルブラウザの場合にnavbarをプッシュする(分離コード)ファイルのタグを簡単に削除します(より高速で小さくなります)。 [その最適化されたが手動のソリューションのコードを分離できるなら。