Openfire Android App



In this tutorial, we're going to be building a realtime group chat for Android using the Scaledrone Java API Client. It will work very similarly to apps such as WhatsApp, Facebook Messager and LINE.

  1. Openfire Spark Android App
  2. Openfire Android App Download

Openfire free download - Openfire, Openfire for Linux, Openfire for Debian, and many more programs. Best Apps Popular Apps. All Windows Mac iOS Android. Mobile App Development & Android Projects for ₹150000 - ₹250000. We are looking for someone who has very good experience working with: 1) Openfire 2) Mobile Clients connect to Openfire server 3) Spark Client customization 4) Openfire Asterisk integration Work De. Openfire is an open source, real-time collaboration server that uses XMPP (Jabber). The server is a breeze to install and easy to use. Users can even connect to the Openfire server with different.

You can find the full source code on GitHub.

This tutorial will teach you:

  • How to build a fully functional group chat.
  • Designing the UI elements such as chat bubbles and text inputs.
  • How to use Scaledrone as the realtime backend of your app.
    The project might seem daunting at first, but the messaging code outside of the layout files is pretty short.

Setting up the project

Start by creating a new Android project. We are using Android Studio, but this tutorial will work with any IDE of choice.

Import the Scaledrone module

To add the Scaledrone dependency to your app, you need to add it to your build.gradle file.

For Android to allow us to connect to the internet, we need to add the internet permission to the manifests/AndroidManifest.xml file:

Defining the UI layout

To start with the UI layout let's build the empty state. It consists of:

An empty ListView into where the messages will go
An EditText where the user can type their message
And finally, an ImageButton as a button to send the message

The base layout is defined in /res/layout/activity_main.xml:

String constants are defined in /res/layout/activity_main.xml:

The icon for the send button is defined in /res/drawable/ic_send_black_24dp.xml:

Next up, chat bubbles!

Our chat app is going to have two type of chat bubbles: a bubble for messages sent by us and bubbles for messages sent by others.

Chat bubble sent by us

The messages sent by us will look dark and be aligned to the right. We're using a drawable to get the border radius effect.

/res/drawable/my_message.xml:

The message itself is just a simple TextView aligned to the right.

/res/layout/my_message.xml:

Android

Chat bubble sent by others

The chat bubble sent by others within the group chat will be light and aligned to the left. In addition to the bubble itself, we will show an avatar (as a simple full-color circle) and the name of the user.

For the avatar let's define a circle shape under /res/drawable/circle.xml:

And for the bubble let's create a shape with curved corners and the sharp corner on the left. This goes in /res/drawable/their_message.xml:

Putting it together their message bubble layout under /res/layout/their_message.xml will look like this:

Hooking up the realtime messaging logic

We're finally done with the layout and can get to the interesting part!

Let's find the EditText view from our layout and extend Scaledrone's RoomListener so we could receive messages. Most of the methods will have minimal code in them, and we'll fill them up as the tutorial goes along.

Connecting to Scaledrone

If you don't have a Scaledrone account yet, open up Scaledrone.com and create a new free account. To successfully connect to Scaledrone you need to get your own channel ID from the Scaledrone's dashboard. To do that go to the dashboard and click the big green +Create Channel button to get started. You can choose Never require authentication for now. Copy the channel ID from the just created channel and replace CHANNEL_ID_FROM_YOUR_SCALEDRONE_DASHBOARD with it.

Connecting to Scaledrone can happen within the onCreate() method, right after we have set up the UI. Scaledrone gives us the ability to attach arbitrary data to a user (users are called members in Scaledrone lingo), we're going to be adding a random name and color.

You might have noticed that we named our name Scaledrone room observable-room. You can name the room anything you want, a single user can actually connect to an infinite amount of rooms to provider for all sorts of application scenarios. However in order for messages to contain the info of the sender the room name needs to be prefixed with observable-. Read more..

To create the MemberData let's implement the getRandomName() and getRandomColor() functions as well as the MemberData class itself.

For the sake of keeping this tutorial simple, we'll define a random username on the client side of the application. Later you can add fancy login functionality to your app. To create a random name, we pre-define two lists of random adjectives and nouns, then combine them randomly.

The random color function will be generating a random seven-character color hex such as #FF0000.

The MemberData class is super minimal and will later be serialized into JSON and sent to users by Scaledrone.

Sending messages

To send (or publish) the message to the Scaledrone room we need to add a onClick() handler to the ImageButton in the activity_main.xml file.

Let's add the sendMessage() function to the MainActivity. If the user has input something we send the message to the same observable-room as we subscribed to above. After the message has been sent we can clear the EditText view for convenience.

Scaledrone will take care of the message and deliver it to everyone that has subscribed to the observable-room room in your channel.

Displaying messages

Openfire android app download

As seen in the layout file the messages are going to be displayed via ListView. To use a ListView you need to create a class that extends android.widget.BaseAdapter. This class is then used as the state of the ListView.

Let's define our MessageAdapter as well as the Message class itself. The Message class will hold all the needed info to render a single message.

The MessageAdapter defines how we render our rows within the ListView.

Receiving messages

Now that we can display and render our chat bubbles we need to hook up the incoming messages with the MessageAdapter that we just created. We can do that by going back to the MainActivity class and finishing the onMessage() method.

Scaledrone uses the popular Jackson JSON library for serializing and parsing the messages, and it comes bundled with the Scaledrone API client. Please see the Jackson docs for best practices on how to parse the incoming Scaledrone messages and users data.

And we're done!

Hopefully, this tutorial helped you build your very own chat app. You can find the full source code or run the working prototype on GitHub. If you have any questions or feedback feel free to contact us.

This tutorial only scratched what Scaledrone can do for you and is the ideal basis for any of your future realtime needs.

Looking to build the same app for iOS using Swift? Check out our iOS chat tutorial.

Last updated February 5th 2019. Now using Scaledrone client 0.6.0.

Introduction

Plugins enhance the functionality of Openfire. This document is adeveloper's guide for creating plugins.

The plugin development is now based on Maven(instead of Ant)

What is Maven

Maven is a project management tool which can manage the complete building life cycle.Maven simplifies and standardizes the project build process. by handling compilation, testing, library dependency, distribution, documentation and team collaboration.The Maven developers claim that Maven is more than just a build tool. We can think of Maven as a build tool with more features.Maven provides developers ways to manage project(Builds,Test,Documentation,Reporting,Dependencies,Releases,Distribution,Mailing List).

Structure of a Plugin

Plugins live in the plugins directory of openfireHome. When a pluginis deployed as a JAR or WAR file, it is automatically expanded into a directory. The files in aplugin directory are as follows:

Plugin Structure

The web directory exists for plugins that need to add contentto the Openfire Admin Console. Further details are below.

The plugin.xml file specifies the main Plugin class. A samplefile might look like the following:

Sample plugin.xml

The meta-data fields that can be set in the plugin.xml file:

  • name -- the name of the plugin.
  • description -- the description of the plugin.
  • author -- the author of the plugin.
  • version -- the version of the plugin.
  • date -- the date the plugin was released. The date must be in the form MM/dd/yyyy, such as 07/21/2006.
  • url -- a URL where additional information about the plugin is available.
  • minServerVersion -- the minimum version of Openfire required to run the plugin (supported by Openfire 2.1.2 and later). If the server version is less than the required value, the plugin will not be started.
  • priorToServerVersion -- the server version up, but not including, on which this plugin can run.
  • minJavaVersion -- the minimum Java specification version the plugin needs to run.
  • databaseKey -- if the plugin requires it's own database tables, the databaseKey element should be set with a schema key name (often the same name as the plugin). Database schema files for each supported database should then be placed in the database directory of the plugin. For example, given the key 'foo', schema files would be called 'foo_mysql.sql', 'foo_oracle.sql', etc. We recommend that you prefix your tables with 'of' (openfire) to avoid conflicts with possible other applications installed in the same database. The scripts should make an entry into the ofVersion table using the key so that schema version information can be tracked, e.g.:
    INSERT INTO ofVersion (name, version) VALUES ('foo', 0);
  • databaseVersion -- the database schema version (if a database schema is defined). New plugins with a database schema should start at version 0. If future versions of the plugin require updates to the schema, those updates can be defined by creating sub-directories in the database/upgrade directory for each version number. For example, the directories database/upgrade/1 and database/upgrade/2 would contain scripts such as 'foo_mysql.sql' and 'foo_oracle.sql' that contain the relevant database changes for each version. Each script should update version information in the ofVersion table, e.g.:
    UPDATE ofVersion set version=1 where name='foo';
  • parentPlugin -- the name of the parent plugin (given as 'foo' for the 'foo.jar' plugin). When a plugin has a parent plugin, the parent plugin's class loader will be used instead of creating a new class loader. This lets plugins work together more closely. A child plugin will not function without its parent present.
  • licenseType -- indicates the license agreement that the plugin is governed by. Valid values are:
    • 'commercial': the plugin is released under a commercial license agreement.
    • 'gpl': the plugin is released under the GNU Public License (GPL).
    • 'apache': the plugin is released under the Apache license.
    • 'internal': the plugin is for internal use at an organization only and will not be re-distributed.
    • 'other': the plugin is released under a license agrement that doesn't fall into one of the other categories. The license agreement should be details in the plugin's Readme.
    If the license type is not set, it is assumed to be other.
Openfire Android AppSeveral additional files can be present in the plugin to provide additional information toend-users (all placed in the main plugin directory):
  • readme.html -- Optional readme file for plugin, which will be displayed to end users.
  • changelog.html -- Optional changelog file for plugin, which will be displayed to end users.
  • logo_small.png -- Optional small (16x16) icon associated with the plugin. It can also be a .gif file.
  • logo_large.png -- Optional large (32x32) icon associated with the plugin. It can also be a .gif file.

Your plugin class must be implement thePlugininterface from the Openfire API aswell as have a default (no argument) contructor. The Plugin interface hasmethods for initializing and destroying the plugin.

Sample plugin implementation

General Plugin Best Practices

When choosing a package name for your plugin, we recommend that you choosesomething distinctive to you and/or your organization to help avoid conflictsas much as possible. For example, if everyone went with org.example.PluginName,even if PluginName was different, you might start running into some conflictshere and there between class names. This is especially true when working withclustering.

.

Modifying the Admin Console

Plugins can add tabs, sections, and pages to the admin console. Thereare a several steps to accomplishing this:

  • An <adminconsole/> section must be added to the plugin.xml file.
  • JSP files must be compiled and put into the classpath of the plugin. A web.xml file containing the compiled JSP servlet entries must be put into the web/ directory of the plugin. Note: the Openfire build script can assist with compiling JSPs and creating the web.xml. This is detailed below.
  • Any images required by your JSP pages must live in web/images/ directory. Only GIF and PNG images are supported.

The <adminconsole /> section of plugin.xml defines additionaltabs, sections and entries in the Admin Console framework. A sampleplugin.xml file might look like the following:

Sample plugin.xml

In this example, we've defined a new tab 'Example', a sidebar section 'My Plugin' and two pages: 'My Plugin Admin'and 'My Plugin Overview'. We've registered my-plugin-admin.jsp respectively my-plugin-overview.jspas the pages.

By default, the tabs, sidebars and pages will be presented in the order in which they are defined. You can, however,define explicit ordering by adding an 'order' attribute to each element. It's numeric value defines order. If noorder is specified, the value 0 (zero) is used as a default. In the example above, the items are ordered using thisconstruct. In the admin console, the 'My Plugin Overview' page will be presented before the 'My Plugin Admin' page,as its 'order' value is lower. If neither item had defined the 'order' attribute, the presentation of both pageswould have been reversed (as it would have used to order in which the pages are defined in XML).

You can override existing tabs, sections, and items by using the existing id attribute values in your own<adminconsole> definition.

Admin Console Best Practices

There are several best practices to consider when making changes tothe Openfire admin console via a plugin. The general theme isthat plugins should integrate seamlessly:

Openfire Spark Android App

  • Integrate into existing tabs and sidebar sections whenever possible instead of creating your own. Only create new tabs for very significant new functionality.
  • Don't use the word 'plugin' in names of tabs, sidebars and items. For example, instead of having an item called 'Gateway Plugin', it could be called 'Gateway Settings'.
  • Try to match the UI of the existing admin console in your custom plugin pages.
  • There is no need to create an admin console entry to show plugin meta-data. Instead, let Openfire inform the user about which plugins are installed and provide plugin management.

Writing Pages for the Admin Console

Openfire uses the Sitemeshframework to decorate pages in the admin console. A globally-defined decorator is applied toeach page in order to render the final output, as in the following diagram:


Creating pages that work with Sitemesh is easy. Simply create valid HTML pages and thenuse meta tags to send instructions to Sitemesh. When rendering the output, Sitemesh willuse the instructions you provide to render the decorator along with any content in thebody of your HTML page. The following meta tags can be used:

  • pageID -- the ID of the page, which must match an entry in the admin console XML described above. Either a pageID or subPageID must be specified.
  • subPageID -- the ID of the sub-page, which must match an entry in the admin console XML described above. Sub-pages are used for administrative actions related to a parent page ID. For example, editing or deleting a particular group. Either a pageID or subPageID must be specified.
  • extraParams (Optional) -- extra parameters that should be passed in to the page. For example, on a page to delete a group it might be the ID of the group. Parameters must be URL encoded.
  • decorator (Optional) -- overrides the Sitemesh decorator to use for the page. A decorator named none is available that will simply render the page without a decorator.
The following HTML snippet demonstrates a valid page:
Sample HTML

Using i18n in your Plugins

It's possible to translate your plugin into multiple languages (i18n). To do so, use the followingprocedure:

  • Create a 'i18n' directory in the root directory of your plugin.
  • Add each resource file using the %[plugin_name]%_i18n '_' language '.properties' naming convention, where [plugin_name] is the name of the plugin directory. See the translator guide for more information about resource bundles.
  • Convert Strings in your JSP files to refer to the internationalized keys. For example:
  • Internationalize Strings in your Java files using the LocaleUtils class:
    org.jivesoftware.util.LocaleUtils.getLocalizedString('some.key.name', '[plugin_name]');
  • Internationalize Strings in your plugin.xml file using the ${var} format:
    <sidebar name='${plugin.sidebar.name}' description='${plugin.sidebar.description}'>
    <description>${plugin.description}</description>

Using the Openfire Build Script

The Openfire build script will help you build and develop plugins. Itlooks for plugin development directories in the following format:

Plugin Structure

The build script will compile source files and JSPs and create a validplugin structure and JAR file. Put your plugin directories in the src/pluginsdirectory of the source distribution and then use ant plugins tobuild your plugins.

Any JAR files your plugin needs during compilation should be putinto the lib directory. These JAR files will also be copied intothe plugin's generated lib directory as part of the build process.

If you create a src/web/WEB-INF/web.xml file, any servlets registered therewill be initialized when the plugin starts up. Only servlet registrations and servletmappings will be honored from the web.xml file. Note: this feature is implemented bymerging your custom web.xml file into the web.xml file generated by the JSP compilationprocess.

Implementing Your Plugin

Plugins have full access to the Openfire API. This provides a tremendousamount of flexibility for what plugins can accomplish. However, there are several integrationpoints that are the most common:

  1. Register a plugin as a Component. Components receive all packets addressed to a particular sub-domain. For example, test_component.example.com. So, a packet sent to joe@test_component.example.com would be delivered to the component. Note that the sub-domains defined as components are unrelated to DNS entries for sub-domains. All XMPP routing at the socket level is done using the primary server domain (example.com in the example above); sub-domains are only used for routing within the XMPP server.
  2. Register a plugin as an IQHandler. IQ handlers respond to IQ packets with a particular element name and namespace. The following code snippet demonstrates how to register an IQHandler:
  3. Register a plugin as a PacketInterceptor to receive all packets being sent through the system and optionally reject them. For example, an interceptor could reject all messages that contained profanity or flag them for review by an administrator.
  4. You can store persistent plugin settings as Openfire properties using the JiveGlobals.getProperty(String) and JiveGlobals.setProperty(String, String) methods. Make your plugin a property listener to listen for changes to its properties by implementing the org.jivesoftware.util.PropertyEventListener method. You can register your plugin as a listener using the PropertyEventDispatcher.addListener(PropertyEventListener) method. Be sure to unregister your plugin as a listener in your plugin's destroyPlugin() method.

Openfire admin tags

Openfire provides useful JSP tags that can be used. To enable them on a JSP page, simply add:Openfire

Openfire Android App Download


<%@ taglib uri='admin' prefix='admin' %>
to the top of your JSP page. The tags include:
  • <admin:ASN1DER value='${ASN.1 DER certificate as a byte[]}'/> (since Openfire 4.0.0) will display an ASN.1 DER encoded certificate in an HTML table.
  • <admin:FlashMessage/> (since Openfire 4.5.0) will display up to three suitably decorated session attributes on the rendered page. The keys of these session attributes are defined by FlashMessageTag.SUCCESS_MESSAGE_KEY, WARNING_MESSAGE_KEY and ERROR_MESSAGE_KEY. This allows messages to be displayed to the user when navigating between pages.

CSRF protection

Admin pages are liable to CSRF attacks. Openfire provides facilities to aid plugin authors to protect against these attacks on their admin pages. To enable CSRF protection:
  1. Set the plugin.xml minServerVersion to 4.5.0 or above as this is when support was added.
  2. Set the plugin.xml csrfProtectionEnabled to true to enable CSRF protection for the plugin. This will;
    • Guard against CSRF attacks for all requests to admin pages except GET requests
    • Set a servlet request attribute with key 'csrf'
  3. Ensure that GET requests do not modify any settings or change any data as this protection is not enabled for GET requests
  4. Ensure that any form submitted in the admin page has a field called csrf whose value is that defined by the request attribute 'csrf' - for example:
    <input name='csrf' value='<c:out value='${csrf}'/>' type='hidden'>
If a CSRF attack is detected, the admin page will be reloaded (with a simple HTTP GET request) with the session attribute FlashMessageTag.ERROR_MESSAGE_KEY set to indicate the problem - it's therefore advised to include the <admin:FlashMessage/> at the top of your JSP page.

NOTE: It is still important to ensure that all your output is properly escaped using <c:out> tags or the equivalent.

Plugin FAQ

Can I deploy a plugin as a directory instead of a JAR?

No, all plugins must be deployed as JAR or WAR files. When a JAR or WAR is not present for the plugin,Openfire assumes that the file has been deleted and that the users wants to destroy the plugin,so it also deletes the directory.

I've made a change to an existing plugin but can't get it to install when I upload it. Why?

Naming is important. The uploaded JAR must match name with the plugin (i.e. the POM artifactId). For example, the Monitoring and Archiving Plugin must be uploaded as monitoring.jar rather than my_better_monitoring.jar.
If you're compiling using the maven-assembly-plugin, be sure to look at the config in the example plugin.