In Monaca / Cordova können Sie verschiedene Plug-Ins verwenden. Bei der Entwicklung einer App gibt es jedoch Fälle, in denen das Standard-Plug-In nicht ausreicht. In einem solchen Fall ist es möglich, das Plug-In zu ändern und die erforderlichen Funktionen hinzuzufügen, dies ist jedoch häufig schwierig, da nicht viele umfassende Informationen vorhanden sind. Daher werde ich als Beispiel für die Reparatur von Plug-Ins das Hinzufügen von Funktionen zu InAppBrowser vorstellen.
Um den Inhalt dieses Artikels auszuprobieren, benötigen Sie eine Umgebung, in der Cordova lokal ausgeführt werden kann. Da der native Code geändert wird, ist Xcode für iOS und Android Studio für Android erforderlich.
(Obwohl es sehr schwierig ist, können Sie es auch versuchen, indem Sie das Cordova-Plugin-In-Appbrowser-Plug-In mit Monacas Pro-Plan usw. als Zip-Datei einbetten und den Code im Plug-In der Monaca-IDE ändern. )
Erst neulich wollte Herr Teratail einen Prozess durchführen, bei dem "nur eine bestimmte URL nicht so verschoben wird, wie sie ist". Lassen Sie uns dies als Thema betrachten. ([JavaScript - Ich möchte verhindern, dass für eine bestimmte URL in Monaca InApp Browser (104255) Teratail "nicht so verschoben wird, wie es ist" (https://teratail.com/questions/104255))
Als Voraussetzung wird im Voraus ein URL-Muster mit einem regulären Ausdruck festgelegt, und der Seitenübergang zum Linkziel wird nicht nur ausgeführt, wenn der reguläre Ausdruck übereinstimmt. Wenn diese Funktion aktiviert ist, wird das Entladeereignis ausgelöst, damit es auf der JS-Seite erfasst werden kann.
Wie ich später vorstellen werde, ist diese Änderung unter https://github.com/knight9999/cordova-plugin-inappbrowser/tree/unload_list verfügbar. Wenn Sie sie also sofort verwenden möchten, versuchen Sie es bitte. schauen Sie bitte.
Mit dieser Modifikation können die folgenden Testfälle betrieben werden.
Programmatisch wird es so aussehen:
document.getElementById('btn').addEventListener('click', function() {
var ref = cordova.InAppBrowser.open('https://github.com/apache/cordova-plugin-inappbrowser', '_blank', 'location=yes', null, ['https:\/\/github\.com\/apache\/cordova-plugin-inappbrowser\/blob\/master\/README\.md']);
ref.addEventListener('unload', function(json) { alert( json.url ); } );
},false);
Ermöglicht das Einfügen einer Liste regulärer Ausdrücke in den fünften Parameter von "cordova.InAppBrowser.open". Wenn es mit diesem kanonischen Ausdruck übereinstimmt, wird die Seite nicht geladen und stattdessen das Entladeereignis ausgelöst.
Da Plug-Ins nicht nur mit Plug-Ins funktionieren, erstellen wir eine Arbeits-App, integrieren das Plug-In und entwickeln es weiter.
Holen Sie sich zuerst den Cordova-Plugin-Appbrowser von github. Gehen Sie in einem Verzeichnis Ihrer Wahl wie folgt vor:
$ git clone https://github.com/apache/cordova-plugin-inappbrowser.git
$ git checkout 1.6.1
Das geklonte Verzeichnis lautet nun "[/ path / to / cordova-plugin-inappbrowser]". Wir werden es basierend auf Version 1.6.1 entwickeln. (Version 1.7.x hat derzeit einen Fehler in UIWebView von iOS, daher basiert dieser Artikel auf der 1.6-Serie.)
Bereiten Sie als Nächstes eine funktionierende App vor, die dieses Plug-In verwendet. Erstellen Sie ein anderes Verzeichnis und gehen Sie wie folgt vor:
$ cordova create sample
$ cd sample
$ cordova platform add [email protected]
$ cordova platform add [email protected]
Hier ist Cordova Cli 6.5.0. Dies ist das Gleiche wie die neueste Version von Monaca heute. Außerdem ist die iOS-Plattformversion 4.4.0 und die Android-Plattformversion 6.2.3, um der neuesten Version von Monaca zu entsprechen.
Installieren Sie anschließend den zuvor geklonten Cordova-Plugin-Appbrowser.
$ cordova plugin add [/path/to/cordova-plugin-inappbrowser]
Jetzt haben Sie eine Entwicklungsumgebung. Danach arbeiten Sie in diesem funktionierenden App-Verzeichnis.
Lassen Sie uns zunächst die Operation überprüfen. Entweder iOS oder Android ist in Ordnung, aber hier werde ich es auf iOS versuchen.
Öffnen Sie die Datei www / index.html und fügen Sie das Button-Tag wie folgt hinzu:
Vor der Korrektur
<div class="app">
<h1>Apache Cordova</h1>
<div id="deviceready" class="blink">
<p class="event listening">Connecting to Device</p>
<p class="event received">Device is Ready</p>
</div>
</div>
Überarbeitet
<div class="app">
<h1>Apache Cordova</h1>
<div id="deviceready" class="blink">
<p class="event listening">Connecting to Device</p>
<p class="event received">Device is Ready</p>
</div>
<button id="btn">Go Btn</button>
</div>
Registrieren Sie dann die Operation, wenn Sie in js / index.js wie folgt auf btn tippen.
Vor der Korrektur
onDeviceReady: function() {
this.receivedEvent('deviceready');
},
Überarbeitet
onDeviceReady: function() {
this.receivedEvent('deviceready');
document.getElementById('btn').addEventListener('click', function() {
var ref = cordova.InAppBrowser.open('https://github.com/apache/cordova-plugin-inappbrowser', '_blank', 'location=yes');
},false);
},
Da dies immer noch ein normaler InAppBrowser ist, habe ich das 5. Argument der open-Methode nicht festgelegt.
$ cordova prepare ios
Öffnen Sie danach das Projekt mit Xcode und überprüfen Sie den Betrieb auf dem tatsächlichen Computer.
$ open platforms/ios/HelloCordova.xcworkspace
Wenn der HelloCorodva-Bildschirm angezeigt wird, haben Sie die BTN-Taste darunter gedrückt, um die Appbrowser-Seite des Github Cordova-Plugin-In anzuzeigen?
Ändern Sie nach Bestätigung des Vorgangs als Änderung des InAppBrowser-Plug-Ins zunächst den JavaScript-Teil. Der JavaScript-Teil ist für Android und iOS üblich, aber zuerst werden wir uns auf iOS konzentrieren und es ändern. Da beim Ändern eines Plug-Ins der Betriebstest viele Male wiederholt wird, ist es effizienter, an dem zu arbeiten, was Sie unter iOS verwenden, es zu überprüfen und nach Abschluss Feedback an die Quelle des Plug-Ins zu geben. Weil es gut ist. (Ich denke schon, aber es kann für einige Leute anders sein)
Der zu reparierende Ort ist normalerweise /plugins/cordova-plugins-inappbrowser/www/inappbrowser.js, aber tatsächlich ist dies nur derjenige, der installiert wurde, als der Stecker hinzugefügt wurde Ich werde es nicht reparieren.
Was in Xcode tatsächlich ausgeführt wird, sind die Plattformen / ios / www / plugins / cordova-plugins-inappbrowser / www / inappbrowser.js. Selbst wenn Sie dies neu schreiben, basiert dies auf jeder Vorbereitung von Cordova. Ich werde das auch nicht beheben, da es zurückkommen wird.
Das Javascript, das während der Plug-Entwicklung geändert werden muss, lautet platform / ios / platform_www / plugins / cordova-plugin-inappbrowser / www / inappbrowser.js. Wenn Sie dies ändern, wird es jedes Mal, wenn Sie Cordova vorbereiten, auf die in Xcode ausgeführten Plattformen / ios / www / plugins / cordova-plugins-inappbrowser / www / inappbrowser.js kopiert.
Lassen Sie uns dies wie folgt ändern.
Vorher ändern:
function InAppBrowser() {
this.channels = {
'loadstart': channel.create('loadstart'),
'loadstop' : channel.create('loadstop'),
'loaderror' : channel.create('loaderror'),
'exit' : channel.create('exit')
};
}
Nach der veränderung:
function InAppBrowser() {
this.channels = {
'loadstart': channel.create('loadstart'),
'loadstop' : channel.create('loadstop'),
'loaderror' : channel.create('loaderror'),
'unload' : channel.create('unload'),
'exit' : channel.create('exit')
};
}
Dem Kanal wurde eine Entladung hinzugefügt.
Ändern Sie es dann wie folgt.
Vor der Korrektur
module.exports = function(strUrl, strWindowName, strWindowFeatures, callbacks) {
// Don't catch calls that write to existing frames (e.g. named iframes).
if (window.frames && window.frames[strWindowName]) {
var origOpenFunc = modulemapper.getOriginalSymbol(window, 'open');
return origOpenFunc.apply(window, arguments);
}
strUrl = urlutil.makeAbsolute(strUrl);
var iab = new InAppBrowser();
callbacks = callbacks || {};
for (var callbackName in callbacks) {
iab.addEventListener(callbackName, callbacks[callbackName]);
}
var cb = function(eventname) {
iab._eventHandler(eventname);
};
strWindowFeatures = strWindowFeatures || "";
exec(cb, cb, "InAppBrowser", "open", [strUrl, strWindowName, strWindowFeatures]);
return iab;
};
Überarbeitet
module.exports = function(strUrl, strWindowName, strWindowFeatures, callbacks, ignoreList) {
// Don't catch calls that write to existing frames (e.g. named iframes).
if (window.frames && window.frames[strWindowName]) {
var origOpenFunc = modulemapper.getOriginalSymbol(window, 'open');
return origOpenFunc.apply(window, arguments);
}
strUrl = urlutil.makeAbsolute(strUrl);
var iab = new InAppBrowser();
callbacks = callbacks || {};
for (var callbackName in callbacks) {
iab.addEventListener(callbackName, callbacks[callbackName]);
}
ignoreList = ignoreList || [];
var cb = function(eventname) {
iab._eventHandler(eventname);
};
strWindowFeatures = strWindowFeatures || "";
exec(cb, cb, "InAppBrowser", "open", [strUrl, strWindowName, strWindowFeatures, ignoreList]);
return iab;
};
Geändert, um ignoreList als fünften Funktionsparameter zu erhalten. Und wenn es leer ist, wird es am Ende des fünften Arguments zum Zeitpunkt der Ausführung als leeres Array hinzugefügt.
Damit ist die Änderung des JavaScript-Teils abgeschlossen.
Als nächstes ändern wir Objective-C. Die Zieldatei ist die Datei platform / ios / HelloCordova / Plugins / cordova-plugin-inappbrowser / CDVInAppBrowser.m. Öffnen Sie es in einem unterstützten Xcode anstelle eines Texteditors und korrigieren Sie es.
Bereiten Sie zunächst _unloadList als Instanzvariable vor. Diese Variable ist eine Variable, die eine Liste der von JavaScript gesendeten regulären Ausdrücke enthält.
Vor der Korrektur
@interface CDVInAppBrowser () {
NSInteger _previousStatusBarStyle;
}
Überarbeitet
@interface CDVInAppBrowser () {
NSInteger _previousStatusBarStyle;
NSArray<NSString *> *_unloadList;
}
Speichern Sie als Nächstes in der Methode open die Liste der von JavaScript übergebenen regulären Ausdrücke in _unloadList.
Vor der Korrektur
- (void)open:(CDVInvokedUrlCommand*)command
{
CDVPluginResult* pluginResult;
NSString* url = [command argumentAtIndex:0];
NSString* target = [command argumentAtIndex:1 withDefault:kInAppBrowserTargetSelf];
NSString* options = [command argumentAtIndex:2 withDefault:@"" andClass:[NSString class]];
Überarbeitet
- (void)open:(CDVInvokedUrlCommand*)command
{
CDVPluginResult* pluginResult;
NSString* url = [command argumentAtIndex:0];
NSString* target = [command argumentAtIndex:1 withDefault:kInAppBrowserTargetSelf];
NSString* options = [command argumentAtIndex:2 withDefault:@"" andClass:[NSString class]];
_unloadList = [command argumentAtIndex:3 withDefault:@[] andClass:[NSArray<NSString *> class]];
Als nächstes beurteilen wir, ob die zum Zeitpunkt des Seitenübergangs angegebene URL mit _unloadList übereinstimmt. Wenn dies übereinstimmt, stoppen Sie den Seitenübergang und lösen das Entladeereignis aus. Dies kann mit der Methode webView: shouldStartLoadWithRequest: navigationType: implementiert werden. Wenn diese Methode JA zurückgibt, ist ein Seitenübergang möglich, und wenn NEIN zurückgegeben wird, ist ein Seitenübergang nicht möglich.
Ändern Sie das Ende dieser Methode wie folgt:
Vor der Korrektur
return YES;
Überarbeitet
__block BOOL unloadFlag = NO;
NSString *urlStr = [url absoluteString];
[_unloadList enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:obj
options:NSRegularExpressionCaseInsensitive
error:&error];
if (! error) {
NSTextCheckingResult *match = [regex firstMatchInString:urlStr
options:0
range:NSMakeRange(0, urlStr.length)];
if (match) {
unloadFlag = YES;
}
}
}];
if (unloadFlag) {
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsDictionary:@{@"type":@"unload", @"url":urlStr}];
[pluginResult setKeepCallback:[NSNumber numberWithBool:YES]];
[self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId];
return NO;
}
return YES;
Dies ist abgeschlossen. Der Bezeichner __block
ist enthalten, da diese Variable (möglicherweise) innerhalb der Blocksyntax geändert wird.
Wechseln wir die App-Seite, um den neuen InAppBrowser zu verwenden
Ändern Sie www / index.js wie folgt:
onDeviceReady: function() {
this.receivedEvent('deviceready');
document.getElementById('btn').addEventListener('click', function() {
var ref = cordova.InAppBrowser.open('https://github.com/apache/cordova-plugin-inappbrowser', '_blank', 'location=yes', null, ['https:\/\/github\.com\/apache\/cordova-plugin-inappbrowser\/blob\/master\/README\.md']);
ref.addEventListener('unload', function(json) { alert( json.url ); } );
},false);
},
Jetzt kann README.md, angegeben durch das 5. Argument der open-Methode, nicht geöffnet werden, und das Entladeereignis wird zu diesem Zeitpunkt ausgelöst.
Die folgenden zwei Dateien wurden diesmal in der Arbeits-App geändert.
platforms/ios/platform_www/plugins/cordova-plugin-inappbrowser/www/inappbrowser.js platforms/ios/HelloCordova/Plugins/cordova-plugin-inappbrowser/CDVInAppBrowser.m
Diese beiden Änderungen müssen im InAppBrowser-Plug-In berücksichtigt werden. Im InAppBroweser-Plug-In-Verzeichnis entspricht Folgendes:
www/inappbrowser.js src/iOS/CDVInAppBrowser.m
Um es einfach auszudrücken, ich denke, es ist in Ordnung, es vollständig zu überschreiben, aber Sie können inappbrowser.js nicht überschreiben.
platforms/ios/platform_www/plugins/cordova-plugin-inappbrowser/www/inappbrowser.js Wenn ich öffne
cordova.define("cordova-plugin-inappbrowser.inappbrowser", function(require, exports, module) {
//Code-Inhalt
});
Bitte überschreiben Sie jedoch nur diesen "Inhalt des Codes" als www / inappbrowser.js. Mit anderen Worten, die Entwicklungs-App Plattformen / ios / platform_www / plugins / cordova-plugin-inappbrowser / www / inappbrowser.js Das Cordova-Plugin-Inappbrowser-Plug-In www / inappbrowser.js ist das ohne die erste und letzte Zeile von.
Für CDVInAppBrowser.m können Sie so wie es ist überschreiben und kopieren.
Die geänderte Version lautet https://github.com/knight9999/cordova-plugin-inappbrowser/tree/unload_list.
Entfernen Sie für Entwicklungs-Apps den bereits integrierten Cordova-Plugin-Inappbrowser und installieren Sie den gesammelten Cordova-Plugin-Inbrowser erneut.
$ cordova plugin rm cordova-plugin-inappbrowser
$ cordova plugin add [/path/to/cordova-plugin-inappbrowser]
Jetzt spiegelt sich das modifizierte JavaScript auch auf der Android-Seite wider. Schauen Sie sich platform / android / platform_www / plugins / cordova-plugin-inappbrowser / www / inappbrowser.js
an.
Und einmal vorbereiten.
$ cordova prepare android
Ich glaube nicht, dass Cordova-Android 6.2.3 mit der neuesten Version von Android Studio 3.0 erfolgreich erstellt werden kann. Laden Sie in diesem Fall gradle-3.2-all.zip von https://services.gradle.org/distributions/ herunter und entpacken Sie es, damit Sie es von Android Studio aus verwenden können. (Auf einem Mac wird es unter / Application / Android Studio.app/Contents/gradle abgelegt.)
Wenn Sie einen EACCESS-Fehler mit cordova compile
usw. erhalten, verwenden Sie den Befehl -d
, um die Details des Fehlers anzuzeigen und zu beheben.
$ cordova compile android -d
Wenn Sie es in Android Studio öffnen und eine Meldung zum Downgrade von Gradle erhalten, führen Sie bitte ein Downgrade durch.
Öffnen Sie dann das Verzeichnis platform / android
in Android Studio. Starten Sie Android Studio und öffnen Sie das Verzeichnis platform / android
mit dem Befehl Vorhandenes Android Studio-Projekt öffnen.
Die zu ändernde Zieldatei lautet "platform / android / src / org / apache / cordova / inappbrowser / InAppBrowser.java".
Zuerst möchte ich "JSONArray" verwenden, also werde ich es importieren.
Überarbeitet
import org.json.JSONArray;
Definieren Sie dann unmittelbar nach der Klassendeklaration von InAppBrowser wie folgt unloadList als Instanzvariable.
Vor der Korrektur
private boolean shouldPauseInAppBrowser = false;
private boolean useWideViewPort = true;
Überarbeitet
private boolean shouldPauseInAppBrowser = false;
private boolean useWideViewPort = true;
private JSONArray unloadList;
Wenn es dann von der open-Methode aus JavaScript aufgerufen wird, wird das durch das 5. Argument zugewiesene Array in JSONArray gespeichert. Ändern Sie die Ausführungsmethode der InAppBrowser-Klasse.
Vor der Korrektur
final String target = t;
final HashMap<String, Boolean> features = parseFeature(args.optString(2));
Überarbeitet
final String target = t;
final HashMap<String, Boolean> features = parseFeature(args.optString(2));
unloadList = args.optJSONArray(3);
Ändern Sie abschließend die Methode shouldOverrideUrlLoading
der InAppBrowserClient-Klasse (in der Datei InAppBrowser.java). Wenn es mit dem regulären Ausdruck übereinstimmt, gibt es hier ein Entladeereignis zurück, um Seitenübergänge zu verhindern. Fügen Sie am Ende dieser Methode einen Beurteilungsprozess hinzu.
Vor der Korrektur
return false;
Überarbeitet
boolean unloadFlag = false;
for (int i=0;i<unloadList.length();i++) {
String regex = unloadList.optString(i);
if (url.matches(regex)) {
unloadFlag = true;
}
}
if (unloadFlag) {
try {
JSONObject obj = new JSONObject();
obj.put("type", "unload");
obj.put("url", url);
sendUpdate(obj, true);
} catch (JSONException ex) {
LOG.e(LOG_TAG, "URI passed in has caused a JSON error.");
}
return true;
}
return false;
Es ähnelt "webView: shouldStartLoadWithRequest: navigationType:" unter iOS, beachtet jedoch, dass der von "shouldOverrideUrlLoading" unter Android zurückgegebene boolesche Wert umgekehrt ist. Es ist eine Methode mit ähnlichen Funktionen, die jedoch nicht mit iOS und Android kompatibel ist. Es ist eine andere Funktion, die jedes Framework hat.
Dies ist abgeschlossen.
Wie bei iOS, um dies im Plug-In widerzuspiegeln, diese Entwicklungs-App
platforms/android/src/org/apache/cordova/inappbrowser/InAppBrowser.java
Cordova-plugin-inappbrowser im Plugin-Verzeichnis
src/android/InAppBrowser.java
Bitte überschreiben.
Das Android-Update wird auch in https://github.com/knight9999/cordova-plugin-inappbrowser/tree/unload_list angezeigt. Außerdem ist die Version des Plug-Ins 1.6.1-Unload.
Unter Verwendung von InAppBrowser als Thema habe ich das Ändern des Cordova / Monaca-Plug-Ins vorgestellt.
Für die Entwicklung / Änderung von Plug-Ins sind Kenntnisse über nativen Code wie Java und Objecitve-C, Kenntnisse über das Cocoa-Framework und das Android-Framework, den CordovaLib-Mechanismus, den Cordova-Plug-In-Einstellungsdateimechanismus und den Hook erforderlich Dies ist eine schwierige Aufgabe, da verschiedene Anforderungen gestellt werden, z. B. Kenntnisse über Skripte. (Für Hook-Skripte habe ich einen Artikel unter https://qiita.com/KNaito/items/65587f5d51974e8b4adf geschrieben. Bitte lesen Sie auch diesen Artikel.)
Die Entwicklung von Plug-Ins erweitert jedoch Ihren Horizont und gibt Ihnen eine Vorstellung davon, wie Sie die Funktionalität Ihrer App aufteilen können. Darüber hinaus kann das Plug-In wiederverwendet werden und ist ein Vorteil für die zukünftige Anwendungsentwicklung. Probieren Sie es also aus.