[JAVA] Ich werde nicht mehr zögern! Anpassen des Cordova / Monaca-Plug-Ins --- Versuchen Sie, das InAppBrowser-Plug-In zu reparieren

Überblick

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. )

Welche Art von Renovierung?

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.

Konkretes Beispiel

Mit dieser Modifikation können die folgenden Testfälle betrieben werden.

  1. Legen Sie "https: \ / \ / github \ .com \ / apache \ / cordova-plugin-inappbrowser \ / blob \ / master \ / README \ .md`" als URL-Muster fest, das Seitenübergänge verhindert. .. (Ich kann README.md nicht lesen)
  2. Öffnen Sie in InAppBrowser https://github.com/apache/cordova-plugin-inappbrowser
  3. Ich kann nicht zu einer Seite wechseln, selbst wenn ich auf den Link zu README.md klicke
  4. Das Entladeereignis wird ausgelöst

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.

Erstellen einer Arbeits-App

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.

Funktionsprüfung

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?

Reparatur des JavaScript-Teils

Ä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.

Ziel-C-Fix

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.

Funktionsprüfung

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.

Feedback zum Plug-In

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.

Zusammenfassung bisher

Die geänderte Version lautet https://github.com/knight9999/cordova-plugin-inappbrowser/tree/unload_list.

Unterstützung für Android

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

Über Android Studio

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.

Java-Code-Änderung

Ö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.

Zusammenfassung bisher

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.

Zusammenfassung

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.

Recommended Posts

Ich werde nicht mehr zögern! Anpassen des Cordova / Monaca-Plug-Ins --- Versuchen Sie, das InAppBrowser-Plug-In zu reparieren
Ich werde nicht mehr zögern! RSpec Einführungsablauf