Dans Monaca / Cordova, vous pouvez utiliser divers plug-ins, mais lors du développement d'une application, il y a des cas où le plug-in standard ne suffit pas. Dans un tel cas, il est possible de modifier le plug-in et d'ajouter les fonctions nécessaires, mais c'est souvent difficile car il n'y a pas beaucoup d'informations complètes. Par conséquent, à titre d'exemple de réparation de plug-in, je vais vous présenter comment ajouter des fonctions à InAppBrowser.
Pour essayer le contenu de cet article, vous avez besoin d'un environnement pour exécuter Cordova localement. De plus, étant donné que le code natif sera modifié, Xcode est requis pour iOS et Android Studio est requis pour Android.
(Bien que ce soit très difficile, vous pouvez également l'essayer en intégrant le plug-in cordova-plugin-inappbrowser sous forme de fichier zip en utilisant le plan Pro de Monaca, etc. et en modifiant le code dans le plug-in sur Monaca IDE. )
L'autre jour, M. Teratail voulait faire un processus qui "seule une URL spécifique ne bouge pas comme elle est", alors pensons à cela comme un thème. (JavaScript - Je veux empêcher "ne pas bouger tel quel" pour une URL spécifique dans Monaca InApp Browser (104255) | teratail)
En tant que condition, un modèle d'URL est défini à l'avance avec une expression régulière, et la page ne passe pas à la destination du lien uniquement lorsque l'expression régulière est mise en correspondance. De plus, lorsque cette fonction est activée, l'événement de déchargement sera déclenché afin qu'il puisse être acquis du côté JS.
Comme je le présenterai plus tard, cette modification est disponible sur https://github.com/knight9999/cordova-plugin-inappbrowser/tree/unload_list, donc si vous souhaitez l'utiliser immédiatement, veuillez l'essayer. regarde s'il te plait.
Avec cette modification, les cas de test suivants peuvent être utilisés.
https: \ / \ / github \ .com \ / apache \ / cordova-plugin-inappbrowser \ / blob \ / master \ / README \ .md
"comme un modèle d'URL qui interdit les transitions de page. .. (Je ne peux pas lire README.md)Par programme, cela ressemblera à ceci:
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);
Vous permet de mettre une liste d'expressions régulières dans le cinquième paramètre de cordova.InAppBrowser.open
. S'il correspond à cette expression canonique, il ne chargera pas la page et déclenchera à la place l'événement de déchargement.
Étant donné que le plug-in ne fonctionne pas uniquement avec le plug-in, créez une application de travail, intégrez-y le plug-in et développez-le.
Tout d'abord, récupérez le navigateur d'application cordova-plugin-in depuis github. Dans un répertoire de votre choix, procédez comme suit:
$ git clone https://github.com/apache/cordova-plugin-inappbrowser.git
$ git checkout 1.6.1
Le répertoire cloné sera désormais [/ path / to / cordova-plugin-inappbrowser]
.
Nous le développerons sur la base de la version 1.6.1. (La version 1.7.x a actuellement un bogue dans UIWebView d'iOS, donc cet article est basé sur la série 1.6)
Ensuite, préparez une application fonctionnelle qui utilise ce plug-in. Créez un autre répertoire et procédez comme suit:
$ cordova create sample
$ cd sample
$ cordova platform add [email protected]
$ cordova platform add [email protected]
Ici, cordova cli est 6.5.0. C'est la même chose que la dernière version de Monaca aujourd'hui. De plus, la version de la plate-forme iOS est 4.4.0 et la version de la plate-forme Android est 6.2.3 afin de correspondre à la dernière version de Monaca.
Et puis, installez le navigateur d'application cordova-plugin-in que vous avez cloné précédemment.
$ cordova plugin add [/path/to/cordova-plugin-inappbrowser]
Vous disposez maintenant d'un environnement de développement. Après cela, travaillez dans ce répertoire d'applications de travail.
Commençons par vérifier le fonctionnement. Soit iOS ou Android, c'est bien, mais ici, je vais l'essayer sur iOS.
Ouvrez le fichier www / index.html et ajoutez la balise button comme suit:
Avant correction
<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>
modifié
<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>
Ensuite, dans js / index.js, enregistrez l'opération lorsque btn est tapé comme suit.
Avant correction
onDeviceReady: function() {
this.receivedEvent('deviceready');
},
modifié
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);
},
Comme il s'agit toujours d'un InAppBrowser normal, je n'ai pas défini le 5ème argument de la méthode ouverte.
$ cordova prepare ios
Après cela, ouvrez le projet avec Xcode et vérifiez le fonctionnement sur la machine réelle.
$ open platforms/ios/HelloCordova.xcworkspace
Lorsque l'écran HelloCorodva apparaît, avez-vous appuyé sur le bouton btn en dessous pour voir la page du navigateur d'application github cordova-plugin-in?
Après avoir confirmé l'opération, en tant que modification du plug-in InAppBrowser, modifiez d'abord la partie JavaScript. La partie JavaScript est commune à Android et iOS, mais nous allons d'abord nous concentrer sur iOS et le modifier. Parce que lors de la modification d'un plug-in, le test de fonctionnement est répété plusieurs fois, il est donc plus efficace de travailler sur ce que vous utilisez sur iOS, de le vérifier et, lorsqu'il est terminé, de donner un retour à la source du plug-in. Parce que c'est bon. (Je pense que oui, mais cela peut être différent pour certaines personnes)
L'endroit à réparer est généralement /plugins/cordova-plugins-inappbrowser/www/inappbrowser.js, mais en fait c'est juste celui qui a été installé lorsque le plug a été ajouté, donc c'est Je ne vais pas le réparer.
En outre, ce qui fonctionne réellement dans Xcode, ce sont les plates-formes / ios / www / plugins / cordova-plugins-inappbrowser / www / inappbrowser.js, mais même si vous réécrivez ceci, il sera basé sur chaque fois que vous préparez cordova. Je ne réglerai pas cela non plus, car il reviendra.
Le javascript à modifier pendant le développement de plug est platform / ios / platform_www / plugins / cordova-plugin-inappbrowser / www / inappbrowser.js. Si vous modifiez cela, chaque fois que vous préparez cordova, il sera copié sur les plates-formes / ios / www / plugins / cordova-plugins-inappbrowser / www / inappbrowser.js fonctionnant sous Xcode.
Modifions cela comme suit.
Changer avant:
function InAppBrowser() {
this.channels = {
'loadstart': channel.create('loadstart'),
'loadstop' : channel.create('loadstop'),
'loaderror' : channel.create('loaderror'),
'exit' : channel.create('exit')
};
}
Après le changement:
function InAppBrowser() {
this.channels = {
'loadstart': channel.create('loadstart'),
'loadstop' : channel.create('loadstop'),
'loaderror' : channel.create('loaderror'),
'unload' : channel.create('unload'),
'exit' : channel.create('exit')
};
}
Ajout d'un déchargement sur le canal.
Puis changez-le comme suit.
Avant correction
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;
};
modifié
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;
};
Changé pour recevoir ignoreList comme cinquième paramètre de fonction. Et s'il est vide, il est ajouté en tant que tableau vide à la fin du cinquième argument au moment de exec.
Ceci termine la modification de la partie JavaScript.
Ensuite, modifions Objective-C. Le fichier cible est le fichier platform / ios / HelloCordova / Plugins / cordova-plugin-inappbrowser / CDVInAppBrowser.m. Ouvrez-le dans un Xcode assisté au lieu d'un éditeur de texte et corrigez-le.
Tout d'abord, préparez _unloadList en tant que variable d'instance. Cette variable contient une liste d'expressions régulières envoyées en JavaScript.
Avant correction
@interface CDVInAppBrowser () {
NSInteger _previousStatusBarStyle;
}
modifié
@interface CDVInAppBrowser () {
NSInteger _previousStatusBarStyle;
NSArray<NSString *> *_unloadList;
}
Ensuite, dans la méthode open, stockez la liste des expressions régulières transmises depuis JavaScript dans _unloadList.
Avant correction
- (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]];
modifié
- (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]];
Ensuite, évaluons si l'URL spécifiée au moment de la transition de page correspond à _unloadList, et si elle correspond, arrêtez la transition de page et déclenchez l'événement de déchargement. Cela peut être implémenté à l'aide de la méthode webView: shouldStartLoadWithRequest: navigationType:. Si cette méthode renvoie OUI, la transition de page sera possible, et si NON est renvoyé, la transition de page ne se produira pas.
Modifiez la fin de cette méthode comme suit:
Avant correction
return YES;
modifié
__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;
C'est tout ce qu'on peut en dire. Le spécificateur __block
est inclus car cette variable est (éventuellement) modifiée à partir de la syntaxe du bloc.
Changeons le côté de l'application pour utiliser le nouveau InAppBrowser
Modifiez www / index.js comme suit:
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);
},
Maintenant, README.md spécifié par le 5ème argument de la méthode open ne peut pas être ouvert, et l'événement de déchargement sera déclenché à ce moment.
Les deux fichiers suivants ont été modifiés dans l'application de travail cette fois.
platforms/ios/platform_www/plugins/cordova-plugin-inappbrowser/www/inappbrowser.js platforms/ios/HelloCordova/Plugins/cordova-plugin-inappbrowser/CDVInAppBrowser.m
Ces deux modifications doivent être reflétées dans le plug-in InAppBrowser. Dans le répertoire du plug-in InAppBroweser, ce qui précède correspond à:
www/inappbrowser.js src/iOS/CDVInAppBrowser.m
Pour le dire simplement, je pense qu'il est normal de l'écraser entièrement, mais vous ne pouvez pas écraser inappbrowser.js.
platforms/ios/platform_www/plugins/cordova-plugin-inappbrowser/www/inappbrowser.js Quand j'ouvre
cordova.define("cordova-plugin-inappbrowser.inappbrowser", function(require, exports, module) {
//Contenu du code
});
Cependant, veuillez remplacer uniquement ce "contenu du code" sous la forme www / inappbrowser.js. En d'autres termes, les plates-formes d'application de développement / ios / platform_www / plugins / cordova-plugin-inappbrowser / www / inappbrowser.js Le plug-in cordova-plugin-inappbrowser www / inappbrowser.js est celui sans la première et la dernière ligne de.
Pour CDVInAppBrowser.m, vous pouvez écraser et copier tel quel.
La version modifiée est https://github.com/knight9999/cordova-plugin-inappbrowser/tree/unload_list.
Pour les applications de développement, supprimez le cordova-plugin-inappbrowser déjà intégré et réinstallez le cordova-plugin-inappbrowser collecté.
$ cordova plugin rm cordova-plugin-inappbrowser
$ cordova plugin add [/path/to/cordova-plugin-inappbrowser]
Désormais, le JavaScript modifié est également reflété du côté Android. Consultez plates-formes / android / platform_www / plugins / cordova-plugin-inappbrowser / www / inappbrowser.js
.
Et préparez-vous une fois.
$ cordova prepare android
Je ne pense pas que Cordova-Android 6.2.3 puisse être construit avec succès avec la dernière version d'Android Studio 3.0. Dans ce cas, veuillez télécharger et décompresser gradle-3.2-all.zip à partir de https://services.gradle.org/distributions/ afin de pouvoir l'utiliser depuis Android Studio. (Sur un Mac, il sera placé sous / Application / Android Studio.app/Contents/gradle)
Si vous obtenez une erreur EACCESS avec cordova compile
etc., utilisez la commande -d
pour afficher les détails de l'erreur et la traiter.
$ cordova compile android -d
De plus, lorsque vous l'ouvrez dans Android Studio, si vous recevez un message pour rétrograder, veuillez rétrograder.
Ensuite, ouvrez le répertoire plates-formes / android
dans Android Studio. Lancez Android Studio et ouvrez le répertoire platform / android
avec le Ouvrir un projet Android Studio existant.
Le fichier cible à modifier est platform / android / src / org / apache / cordova / inappbrowser / InAppBrowser.java
.
Tout d'abord, je veux utiliser JSONArray
, donc je vais l'importer.
modifié
import org.json.JSONArray;
Ensuite, immédiatement après la déclaration de classe d'InAppBrowser, définissez unloadList comme variable d'instance comme suit.
Avant correction
private boolean shouldPauseInAppBrowser = false;
private boolean useWideViewPort = true;
modifié
private boolean shouldPauseInAppBrowser = false;
private boolean useWideViewPort = true;
private JSONArray unloadList;
Ensuite, lorsqu'il est appelé par la méthode open à partir de JavaScript, le tableau affecté par le 5ème argument est stocké dans JSONArray. Modifiez l'intérieur de la méthode d'exécution de la classe InAppBrowser.
Avant correction
final String target = t;
final HashMap<String, Boolean> features = parseFeature(args.optString(2));
modifié
final String target = t;
final HashMap<String, Boolean> features = parseFeature(args.optString(2));
unloadList = args.optJSONArray(3);
Et enfin, modifiez la méthode shouldOverrideUrlLoading
de la classe InAppBrowserClient (située dans le fichier InAppBrowser.java). Ici, s'il correspond à l'expression régulière, il renvoie un événement de déchargement pour empêcher les transitions de page. Ajoutez un processus de jugement à la fin de cette méthode.
Avant correction
return false;
modifié
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;
C'est similaire à webView: shouldStartLoadWithRequest: navigationType:
sur iOS, mais notez que la valeur booléenne retournée par shouldOverrideUrlLoading
sur Android est inversée. C'est une méthode avec des fonctionnalités similaires, mais elle n'est pas compatible avec iOS et Android. C'est une fonction différente de chaque cadre.
Ceci est complet.
Comme avec iOS, afin de refléter cela dans le plug-in, cette application de développement
platforms/android/src/org/apache/cordova/inappbrowser/InAppBrowser.java
Cordova-plugin-inappbrowser dans le répertoire plugin
src/android/InAppBrowser.java
Veuillez écraser.
Le correctif Android est également reflété dans https://github.com/knight9999/cordova-plugin-inappbrowser/tree/unload_list. De plus, la version du plug-in est 1.6.1-unload.
En utilisant InAppBrowser comme thème, j'ai présenté comment modifier le plug-in Cordova / Monaca.
Le travail de développement / modification de plug-in nécessite la connaissance du code natif tel que Java et Objecitve-C, la connaissance du framework Cocoa et du framework Android, ainsi que du mécanisme CordovaLib, du mécanisme de fichier de configuration du plug-in cordova et des hooks. C'est une tâche difficile car il existe diverses exigences telles que la connaissance des scripts. (Pour les scripts de hook, j'ai écrit un article à https://qiita.com/KNaito/items/65587f5d51974e8b4adf, veuillez donc vous y référer également.)
Cependant, le développement de plug-ins élargira vos horizons et vous donnera une idée de la manière de décomposer les fonctionnalités de votre application. De plus, le plug-in peut être réutilisé et sera un atout pour le développement futur de l'application, alors essayez-le.