Create cordova plug-ins from scratch ( including four major components, shelf package, and life cycle)

Keywords: Android xml Java github

1 Introduction

This article will explain the creation and writing of cordova plug-ins in detail plugin.xml Configuration, aar+jar+so package configuration, static resource configuration, four components

2 start a simple cordova plug-in

2.1 initialize Cordova Plug-in Development Directory

Ensure Cordova is installed before initialization

cordova create CordovaProject io.cordova.hellocordova CordovaApp
Cordova project is the name of the directory where the application was created.
io.cordova.hellocordova       Is the default reverse domain value. If possible, you should use your own domain values.
CordovaApp is the title of your app.

I create Cordova project under jobProject

$ cordova create CordovaProject com.ths.toast ThsToast

The following structure will be generated in the root directory


After adding platforms and plugins, you can package in this directory

CordovaProject$ cordova build android

The package name of the app is com.ths.toast , the application name is ThsToast

2.2 installation of plugman

plugman is a command-line tool for installing and uninstalling plug-ins for the Apache Cordova project.
Enter the Cordova project directory and install plugman

$ npm install -g plugman

2.3 creating plug-ins

2.3.1 create the simplest Toast plug-in

$plugin create -- name [plugin name] - plugin_id [plug in ID] - plugin_ Version [plug-in version]

To facilitate management, the plug-in is created in the plugins folder under the Cordova project directory

plugins$ plugman create --name ThsToast --plugin_id cordova-plugin-ths-toast --plugin_version 1.0.0


Then manually rename the ThsToast directory to and the plugin above_ The same value as ID: Cordova plugin ths toast. Here and above the ths represent the company's unified identity, usually an English string

Enter the plug-in directory and add the platform environment supported by plug-ins

cordova-plugin-ths-toast$ plugman platform add --platform_name android
cordova-plugin-ths-toast$ plugman platform add --platform_name ios

After adding, android and ios directories will be generated in Cordova plugin ths toast directory. Here, only ThsToast of android environment is defined,
The content of the generated file is as shown in the figure


Note: the name should not conflict with the Android native method. For example, if ThsToast is changed to Toast, it will conflict with android.widget.Toast The toast class in has the same name, resulting in a build error


2.3.2 plug in configuration

After adding the platform, the plugin.xml The following will be added to the file

Modification plugin.xml The contents of the document are as follows

<?xml version='1.0' encoding='utf-8'?>
<plugin id="cordova-plugin-ths-toast" version="1.0.0" xmlns="http://apache.org/cordova/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android">
    <name>Toast</name>
    <js-module name="ThsToast" src="www/ThsToast.js">
        <!-- target modify, adopt window.ThsToast.show or ThsToast.show Can be called api -->
        <clobbers target="ThsToast" />
    </js-module>

    <platform name="android">
        <config-file parent="/*" target="res/xml/config.xml">
            <feature name="ThsToast">
            <!-- param value Modify the full path of the main class to the final packaging output -->
                <param name="android-package" value="org.apache.cordova.thstoast.ThsToast" />
            </feature>
        </config-file>
        <config-file parent="/*" target="AndroidManifest.xml" />
        <!-- target-dir Modify and output the complete directory path of the main class to the final packaging output -->
        <source-file src="src/android/ThsToast.java" target-dir="src/org/apache/cordova/thstoast" />
    </platform>

    <platform name="ios">
        <config-file parent="/*" target="config.xml">
            <feature name="ThsToast">
                <param name="ios-package" value="ThsToast" />
            </feature>
        </config-file>
        <source-file src="src/ios/ThsToast.m" />
    </platform>
</plugin>

Revised www/ThsToast.js , by the way, the exec method is the original method that calls the cordova plug-in. The 'ThsToast','show' and [arg0] passed by the method correspond to the Android parameters of success and error/ ThsToast.java Class class name, action and args in, callbackContext.success , callbackContext.error



Modify android/ThsToast.java Documents,

2.3.3 write the README, make the mermaid uneasy, and then give the mermaid a fishing rod

cordova-plugin-ths-toast$ touch README.md

2.3.4 initialization plug-in

npm init

When prompted, name will enter the plug-in id, and the rest will be filled in according to the prompts. If not clear, press enter directly to the end, and a package.json file

{
  "name": "cordova-plugin-ths-toast",
  "version": "1.0.0",
  "description": "show toast",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/qtpalmtop/cordova-plugin-ths-toast.git"
  },
  "author": "lilin",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/qtpalmtop/cordova-plugin-ths-toast/issues"
  },
  "homepage": "https://github.com/qtpalmtop/cordova-plugin-ths-toast#readme"
}

Then modify package.json,keywords keyword configuration is to display plug-ins in Cordova Plugin Search, and engines configuration is that plug-ins may list dependencies of multiple distributions, so as to provide guidance to Cordova CLI when selecting plug-in versions to be obtained from npm, aiming at final replacement plugin.xml engine element in.
For details, please refer to cordova creating plug-ins

{
  "name": "cordova-plugin-ths-toast",
  "version": "1.0.0",
  "description": "show toast",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/qtpalmtop/cordova-plugin-ths-toast.git"
  },
  "author": "lilin",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/qtpalmtop/cordova-plugin-ths-toast/issues"
  },
  "homepage": "https://github.com/qtpalmtop/cordova-plugin-ths-toast#readme",
  "keywords": [
    "ecosystem:cordova",
    "cordova-android",
    "cordova-ios"
  ],
  "engines": {
    "cordovaDependencies": {
      "2.0.0": {
        "cordova-android": ">=3.6.0"
      },
      "4.0.0": {
        "cordova-android": ">=3.6.0",
        "cordova-windows": ">=4.4.0"
      },
      "6.0.0": {
        "cordova": ">100"
      }
    },
    "node": ">=6.0.0"
  }
}

2.3.5 publishing plug-ins

After publishing, you can normally pass Cordova plugin add Cordova plugin ths toast in the project ThsToast.show() use, but to use in the angular project, we need to develop custom plug-in api. Let's start the api module development of ionic native

cd cordova-plugin-ths-toast
npm login
npm publish

3 Advanced Cordova development

3.1 Activity: activity of four components

In short, the activity is equivalent to the angular page, vue of vue, which is a ui page that can contain components.

1. Open ordinary activities

// Application context
Context context = cordova.getActivity().getApplicationContext();
String pkgName  = context.getPackageName();

// Open app app
Intent intent = context
        .getPackageManager()
        .getLaunchIntentForPackage(pkgName);

// Open XxxActivity
// Intent intent=new Intent(cordova.getActivity(), XxxActivity.class);

// To open an application, category must be added_ LAUNCHER
intent.addCategory(Intent.CATEGORY_LAUNCHER);

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);

// Start app
context.startActivity(intent);

// Launch activity
// cordova.getActivity().startActivity(intent);

// Start activity with return value
// cordova.startActivityForResult((CordovaPlugin) this, intent, 0);
  1. Open the third-party Android SDK activities, such as: Baidu map uri
// If you have Baidu map URI details: http://lbsyun.baidu.com/index.php?title=uri/api/android
Intent intent = Intent.parseUri("intent://map/direction?"
                        + "origin="+options.getOrigin4Baidu()
                        + "&destination="+options.getDestination4Baidu()
                        + "&mode="+options.getModel4Baidu()
                        + "&coord_type=wgs84&referer=Autohome|GasStation#Intent;scheme=bdapp;package=com.baidu.BaiduMap;end",0);
                        
cordova.getActivity().startActivity(intent);

3.2 BroadcastReceiver: broadcast of four major components

Broadcast is actually an event push and accept center within the scope of app, similar to iframe's postMessage.

There is no difference between native broadcast and static broadcast. In general, there are many plug-ins for static broadcast

plugin.xml Static registration broadcast

3.3 Service: Service of four components

Services can synchronize or execute some small tasks, small processes, and even operate on ui pages of other processes, which can be similar to the angular service.

Same usage as native Service

plugin.xml

3.4 ContentProvider: content provider of four components

The content provider is actually a mobile phone system wide API scheduling center, for example, it can read and modify the contents of the address book and album.


plugin.xml , access to other applications requires configuration of application read-write permissions

<config-file target="AndroidManifest.xml" parent="/manifest">
  <uses-permission android:name="android.permission.READ_CALENDAR"/>
  <uses-permission android:name="android.permission.WRITE_CALENDAR"/>
</config-file>

<!-- If it's not up there Calendar This system provider(android.provider.*),You need to register -->
<config-file target="AndroidManifest.xml" parent="/*/application">
    <provider
        android:name="org.apache.cordova.provider.TestContentProvider"
        android:authorities="org.apache.cordova.provider.testprovider"
        android:exported="false" />
</config-file>

3.5 jar, aar, so shelf package and resource configuration

3.5.1 jar

The jar package can be understood as a collection of APIs. After decompression, all classes are compiled, but they do not contain resource files. You can use the classes directly.

Introducing jar package class

The jar package path is in the libs directory


plugin.xml

3.5.2 so

so is developed on the NDK platform. NDK is used to develop software for Android phones, but unlike SDK, it uses C language, while SDK uses Java language. The software developed by NDK runs directly in the Android environment, and can only run on a specific CPU instruction set machine.

so can be configured in libs directory

3.5.3 aar

aar is similar to jar, but it contains all resources, class and res resource files

aar and gradle under libs

To configure flatDir in repositories and compile in dependencies in gradle

plugin.xml

Use: for example, jump activity

3.5.4 static resources and java file configuration

Put static resources in res directory


plugin.xml Configure the current path and output path through resource file and source file. The default path of static resource is src/android/res/xxx, the output path is res/xxx, and the default path of java file is src/android/Xxx.java The output directory is src / package / name / word /. Note that target dir is the directory path and target is the file path.

3.6 meta data: parameters passed in when adding plug-ins

Take a sharing plug-in as an example

plugin.xml : configure preference to receive the value of the parameter variable passed by the user, configure meta data in config file, and save the parameter key value information for calling java class.


Plugin.java : Pass cordova.getActivity().getPackageManager().getApplicationInfo(cordova.getActivity().getPackageName(), PackageManager.GET_META_DATA) obtain the appinfo of the parameter storage object, and then pass the appInfo.metaData.getType(key) get the parameter value, GetType has getString, getInt

There are two ways to pass in plug-in parameters,

1. When installing with cordova, use -- variable key=value to pass in

cordova plugin add cordova-plugin-share --variable WEIXIN_APP_ID=xxx --variable WEIXIN_APP_SECRET=xxx --variable QQ_APP_ID=xxx --variable QQ_APP_KEY=xxx

2. After the plug-in is added, the config.xml Add manually in

<plugin name="cordova-plugin-share" spec="1.0.0">
    <variable name="WEIXIN_APP_ID" value="xxx" />
    <variable name="WEIXIN_APP_SECRET" value="xxx" />
    <variable name="QQ_APP_ID" value="xxx" />
    <variable name="QQ_APP_KEY" value="xxx" />
</plugin>

3.7 authority

When you need to use a function of the system, you must add the permission query configuration, all permissions View here

<config-file target="AndroidManifest.xml" parent="/manifest">
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
</config-file>

3.8 CordovaPlugin life cycle and its own method

3.9.1 execute: execute plug-in method

Call the plug-in execution method. The first parameter, action, is the called method name, the second parameter, args, is the passed in parameter array, and the third parameter, CallbackContext, is the passed in callback function context callbackContext.success(message) and callbackContext.error(errorMessage) input the callback parameter;

@Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
}

3.8.2 initialize: initialize

Called after the implementation of the plug-in constructor and the initialization of the field, the excute method has not been executed at this time.

@Override
public void initialize (CordovaInterface cordova, CordovaWebView webView) {}

3.8.3 pluginitialize: no parameter initialization

After the plug-in constructor function and the field initialization, there is no parameter. The excute method has not been implemented at this time. pluginInitialize does not support cordova 3.0-3.5.

@Override
protected void pluginInitialize() {}

3.8.4 onStart: activity start cycle

The activity is being started, visible, but not yet in the foreground.

@Override
public void onStart() {}

3.8.5 onResume: activity recovery cycle

The activity is in the foreground and can interact with the user.

/**
 * Called when the activity will begin to interact with the user.
 *
 * @param multitasking Indicates whether multitasking is open for the application
 */
@Override
public void onResume(boolean multitasking) {
    super.onResume(multitasking);
    // deviceready();
}

3.8.6 onPause: activity pause cycle

An activity is in a stopped state and is usually called when it is to leave the activity. Next onStop() will be called immediately. If a dialog box pops up, onStop will not be called.

/**
 * Called when the system is about to start resuming its previous activity
 *
 * @param multitasking Indicates whether multitasking is open for the application
 */
@Override
public void onPause(boolean multitasking) {
    super.onPause(multitasking);
}

3.8.7 onStop: activity stop cycle

The activity is about to stop and is completely invisible.

/**
 * Call before activity stops
 */
@Override
public void onStop() {
    super.onStop();
}

3.8.8 onReset: active reset cycle

This method indicates that the activity is restarting, and the activity is restored from the stopped state to the running state. Usually, this method will be called by the activity when the previous activity returns to this activity.

/**
 * Called when the view navigates
 */
@Override
public void onReset() {}

3.8.9 onActivityResult: return activity data

When returning from another activity to the current activity, the onActivityResult in the current activity can receive the return data of the just activity.

@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
    super.onActivityResult(requestCode, resultCode, intent);
}

3.8.10 onDestroy: activity destruction cycle

Before the activity is completely destroyed, we can do some resource releasing operations here.

/**
 * Call before activity destruction
 */
@Override
public void onDestroy() {
    // deviceready = false;
}

4 Summary

From creating a simple cordova custom plug-in to the configuration and use of the four components, we also talked about how to import jar, aar, so and static resources. Finally, we summed up the common life cycle. We can see that we should have the basic ability to create and rewrite plug-ins independently. The rest is to see and use cordova plugin more by ourselves, and practice to get the truth It's been written for a week. After all, it's a front-end development. If there's something that's not summarized in place or missed, please point out more. Thank you! If this article is helpful or enlightening to you in front-end or other directions, please give me a compliment:)

Posted by mook on Sun, 14 Jun 2020 21:06:44 -0700