Two years ago I became interested in mobile development for Android. Then I wrote a simple application for parsing websites. The program code was written in Java. It is a very powerful language, but for writing simple, lightweight applications that do not perform complex tasks, its object-oriented paradigm seemed to me not too helpful. At that time, I was just starting to get familiar with JavaScript. Initially, he attracted me with his simplicity, then I began to open up more and more opportunities in him. I was familiar with HTML5 and CSS3, creating fun web pages for fun.
Once I learned about Apache Cordova - a framework that allows you to write mobile applications in HTML, CSS and JavaScript. I immediately installed it.
Working with Cordova was really convenient. However, judging by the number of topical articles on the Internet, the framework has not yet received widespread use. Although it is implemented, for example, the Wikipedia mobile application.
I believe that this is due to the lack of functionality of the standard Cordova API. To work with Bluetooth, speech recognition and synthesis, camera, etc. plugins are required. Plug-ins can be written for one or several platforms in their native language.
For the needs of the developers were written thousands of plug-ins that are publicly available. I was pleased until the moment when I needed to create an application that even after its closure would send a push notification to the user after a certain period of time. On Android, this function is implemented through a background process. A plug-in for creating something like this was not found. The https://github.com/katzer/cordova-plugin-background-mode plugin allowed to run a background process that stopped as soon as the application was closed.
The forums claimed that it was impossible to create a full-fledged background process on Cordova. But who prevents you from writing your own plugin for these needs? After several days of work, I managed to write a plugin and an application that, when it started, started sending notifications to the user every 5 seconds.
On the way to create an application and a plugin, I want to tell in this post.
Before installing Cordova, be sure to install the Android SDK, Apache Ant and Java.
Then add them to the system path:
On Windows: Type "Control Panel" in the search. Click on Advanced system settings . Click Environment Variables . Under Environment Variables, select the PATH environment variable. Click Edit .
Add to the end of the line ;C:\Development\adt-bundle\sdk\platform-tools;C:\Development\adt-bundle\sdk\tools;%JAVA_HOME%\bin;%ANT_HOME%\bin
.
On Mac / Linux: open .bash_profile with the open ~/.bash_profile
command. Add the system variables there: export PATH=${PATH}:/Development/adt-bundle/sdk/platform-tools:/Development/adt-bundle/sdk/tools
. Add paths for Java and Apache Ant if there are none.
Be sure to specify your path to the folders.
From https://nodejs.org/en/download/, we install Node.js, which allows translating JavaScript into native codes. The platform contains the npm package manager, with which we will install Cordova.
Open a command prompt or terminal and install Cordovanpm install -g cordova
cordova create MyApp com.app.myapp MyApp
The first argument is the name of the folder where the application codes and files will be stored. In this case, it is MyPluginApp.
The second argument is the name of the application package, its unique identifier.
The third argument is the name of the application that will be visible to the user. Usually the same as the folder name.
Do not forget to go to the application folder:
cd MyApp
cordova platform add android
cordova run android
Now we will create a plugin that will conduct the API to the Service class, which is responsible for the background process.
To write a plugin, you need to create a regular folder. Create it in the same directory as the application folder. Let's call it MyPlugin.
Any plugin contains a plugin.xml file. Create and add it to the plugin folder.
plugin.xml:
<?xml version="1.0" encoding="utf-8"?> <plugin xmlns="http://www.phonegap.com/ns/plugins/1.0" id="com.example.myplugin" version="1.0"> <name>MyPlugin</name> <engines> <engine name="cordova" version=">=3.4.0"/> </engines> <asset src="www/MyPlugin.js" target="js/MyPlugin.js"/> <js-module src="www/MyPlugin.js" name="MyPlugin"> <clobbers target="MyPlugin" /> <!-- , --> </js-module> <platform name="android"> <config-file target="res/xml/config.xml" parent="/*"> <feature name="MyPlugin"> <param name="android-package" value="com.example.plugin.MyPlugin"/> <!-- java- --> </feature> </config-file> <config-file target="AndroidManifest.xml" parent="/manifest/application"> <service android:name="com.example.plugin.MyService" /> <!-- () --> </config-file> <framework src="com.android.support:support-v4:+" /> <!-- , java- --> <!-- java- --><source-file src="src/android/MyPlugin.java" target-dir="src/com/example/plugin/"/> <!-- java-, Service --><source-file src="src/android/MyService.java" target-dir="src/com/example/plugin/"/> </platform> </plugin>
This file contains information about the plugin, files and libraries necessary for its operation, as well as API features. As you can see, we refer to one javascript and two java files. So create them!
Add the www folder to the MyPlugin folder and create the MyPlugin.js file there. There we will describe the functions with which the application can interact with the native code. That is, this file will serve as a kind of guide between the JavaScript code of the application developer and the Java code of the plugin developer.
MyPlugin.js:
module.exports = { runBackground: function (successCallback, errorCallback) { cordova.exec(successCallback, errorCallback, "MyPlugin", "runBackground", []) } }
The plugin has one single runBackground function that runs the background process that sends notifications. As arguments, we give it a function, which is called in the case of successful execution of a command, and a function that reports an error. Next comes the class name of the native code to which the command will be sent and the name of the command itself. At the end, an array of additional arguments follows, which we will not touch.
Finally, let's get down to working with native code. Create a folder src / android inside MyPlugin. There will be two Java-classes: MyPlugin.java and MyService.java.
MyPlugin.java:
package com.example.plugin; import org.apache.cordova.*; import org.json.JSONArray; import org.json.JSONException; import android.widget.Toast; import android.content.Context; import android.app.Notification; import android.app.NotificationManager; import android.content.Intent; import android.os.Bundle; import android.support.v4.app.NotificationCompat; public class MyPlugin extends CordovaPlugin { @Override public boolean execute(String action, JSONArray data, CallbackContext callbackContext) throws JSONException { if (action.equals("runBackground")) { Context context = cordova.getActivity().getApplicationContext(); Intent service = new Intent(context, MyService.class); context.startService(service); return true; } else { return false; } } }
First, libraries are imported, including org.apache.cordova. *, Which allows you to interact with a Cordova-based application. Further we can meet Notification and NotificationManager - libraries for working with notifications. For the sake of the NotificationCompat library, we added the line <framework src="com.android.support:support-v4:+" />
to plugin.xml.
As soon as the application calls any function of the plugin, the execute method is executed, to which the action
string is passed. Depending on the value of this string, different sets of actions are performed. In our plugin, action
can take only one value - runBackground. An object of our background process is created and called.
MyService.java:
package com.example.plugin; import org.apache.cordova.*; import android.app.Notification; import android.app.NotificationManager; import android.app.Service; import android.content.Intent; import android.os.Handler; import android.os.IBinder; import android.content.Context; import android.os.Handler; import android.support.v4.app.NotificationCompat; public class MyService extends Service { Handler mHandler = new Handler(); @Override public int onStartCommand(Intent intent, int flags, int startId) { mHandler.postDelayed(ToastRunnable, 5000); return START_STICKY; } @Override public IBinder onBind(Intent intent) { return null; } Runnable ToastRunnable = new Runnable() { public void run() { Context context = getApplicationContext(); NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context) .setSmallIcon(context.getApplicationInfo().icon) .setWhen(System.currentTimeMillis()) .setContentTitle("It works!") .setTicker("Ticker") .setContentText("Text") .setNumber(1) .setAutoCancel(true); mNotificationManager.notify("App Name", 228, mBuilder.build()); mHandler.postDelayed( ToastRunnable, 5000); } }; }
This class is an ordinary Service. When the service starts, its onStartCommand
method returns START_STICKY. Thanks to this, even after the application is closed, the process continues. To send push notifications every 5 seconds, a Runnable thread was created, which is called by the handler every 5 seconds. In the body of the stream, a notification is created and sent.
Go to the application directory and add our plugin:
cordova plugin add ../MyPlugin
.
Then go to www / js / index.js and rewrite the onDeviceReady method as follows:
onDeviceReady: function() { app.receivedEvent('deviceready'); var failure = function() { alert("Error calling MyPlugin"); } MyPlugin.runBackground(function() {}, failure); }
Through the MyPlugin object, the runBackground function is called, to which we pass a function, which is called in case of an error, and an empty function if everything is successful. This function has been left empty, since the confirmation of a successful call from us is already sending a push notification.
Now we have a working app that sends push notifications every 5 seconds even after we close it.
I want to say that this is just a framework for creating useful applications. So, for example, you can remind a person that it's time to go for a run (not every 5 seconds, of course). In any case, this example shows that Cordova using plug-ins is not inferior in functionality to native applications.
The source code of the application and the plugin can be downloaded from the links: the application itself , the plugin .
Source: https://habr.com/ru/post/282914/
All Articles