目录

一、開發環境設置.... 3

1.1 JDK 安裝.... 3

1.2 MySql Server安裝.... 4

1.3 OpenFire安裝.... 6

1.4 Openfire Admin 功能.... 14

1.4.1 用戶摘要:.... 16

1.4.2 組摘要:.... 16

1.4.3 用戶組管理:.... 17

1.4.4 發送管理消息:.... 17

二、TVBox Client APK開發.... 18

2.1 自啟動Webview播放視頻.... 18

2.1.1自啟動任務:.... 18

2.1.2WebView 播放視頻.... 19

2.2 登錄Openfire並抓取群組數據.... 20

2.2.1Openfire 登錄設定.... 20

2.2.2Openfire登錄及數據抓取.... 22

2.3 Openfire自動註冊登錄並加入群組.... 25

2.3.1 Openfire自動註冊登錄.... 26

2.3.2加入群組並建立消息監聽.... 27

三、FHWTVBox Manager 開發.... 28

3.1 界面及功能.... 28

3.1.1群組管理.... 29

3.1.2機頂盒管理.... 30

3.2 開發涉及技術點.... 30

3.2.1Java Swing組件.... 30

3.2.2生成可執行jar. 30

3.2.3 HttpClient獲取及操作openfire 數據.... 31

FHWTVBox ClientFHWTVBoxManager整合應用.... 34

4.1FHWTVBox Client端安裝設定.... 34

4.2FHWTVBoxManager 管理操作.... 37

androidFHWTVBox Admin. 42

FHWTVBox Openfire Plugin JSP. 47

6.1 TVBox JSP Plugin插件及部署.... 47

6.2TVBox Plugin登錄及使用.... 48

6.2.1 發送消息.... 49

6.2.2查看回复.... 50

6.2.3 機頂盒管理.... 52

6.3TVBox Plugin開發.... 53

6.3.1Openfire源碼部署及設定.... 53

6.3.2Openfire源碼編譯.... 56

6.3.3Openfire plugin 代碼結構.... 57

6.3.4Openfire plugin Class開發.... 61

6.3.5Openfire plugin JSP開發.... 64

FHW TVBox按群組管理     69

正文

一、开发环境设置

1.1 JDK 安装

运行jdk-6u27-windows-i586.exe(或者其他更高版本的JDK安装程序,64位windows系统,请安装64位JDK),设定好环境变量,按照提示一步一步安装完毕。

1.安装JDK,安装过程中可以自定义安装目录等信息,例如我们选择安装目录为D:/java/jdk1.6.0_27;

2.安装完成后,右击“我的计算机”,点击“属性”;

3.选择“高级”选项卡,点击“环境变量”;

4.在“系统变量”中,设置3项属性,JAVA_HOME,PATH,CLASSPATH(大小写无所谓),若已存在则点击“编辑”,不存在则点击“新建”;

5.JAVA_HOME指明JDK安装路径,就是刚才安装时所选择的路径D:/java/ jdk1.6.0_27,此路径下包括lib,bin,jre等文件夹(此变量最好设置,因为以后运行tomcat,eclipse等都需要依此变量);

Path使得系统可以在任何路径下识别java命令,向已有的PATH变量中继续添加如下:  %JAVA_HOME%/bin;%JAVA_HOME%/jre/bin, 记得要与前一个用; 隔开;

    CLASSPATH为java加载类(class or lib)路径,只有类在classpath中,java命令才能识别,设为:    .;%JAVA_HOME%/lib/dt.jar;%JAVA_HOME%/lib/tools.jar (注意要加 . 表示当前路径)

6.“开始”->;“运行”,键入“cmd”;

7.键入命令“java -version”,“java”,“javac”几个命令,出现以下画面,说明环境变量配置成功;若不成功,请重复前面的步骤仔细检查。

8. 键入命令 java -Xms4095M -Xmx4096M –version 如果报错, 说明为32位JDK因为其理论内存最大为4G;如果不报错,说明为64位JDK。

1.2 MySql Server安装

先下载MySql Server,目前我们安装的是mysql-5.1.31-win32.msi版本(64位windows系统,请安装mysql-essential-5.1.59-winx64.msi)的,按照提示一步一步安装完毕即可。记住设定的root用户的密码,下面会用到。

因MySql Server的windows版与linux版对大小写的敏感度不一致,因此需要设定下:

a. Windows下在MySql Server安装目录下,找到my.ini档,在最后面加上:lower_case_table_names=0, (0为大小写敏感,1为大小写不敏感), 然后重启MySql Server;

b. Linux下,在/etc/my.cnf中的[mysqld]后添加lower_case_table_names=0 (0为大小写敏感,1为大小写不敏感),重启MySql Server即可。

mySql安装完毕,需打开MySql Query Browser(或者用其他数据库连接工具也可以),创建一个数据库给Openfire使用(通常命名为openfire):

登录后,在Resultset 1中输入create  database  openfire,执行;

或者在右边Schemata里的任一数据库上单击右键,选择create new schema:

Schema name输入openfire后点击OK:

后在右边Schema里的任一数据库上单击右键选择refresh,就会看到openfire数据库:

1.3 OpenFire安装

运行下载的openfire安装程序(openfire_3_7_1.exe) ,按照提示,选择语言(中文简体或英文均可)及安装路径,完成安装。

待安装程序运行完后,会运行一个OpenFire的程序(如下图),当出现如图所示的接口时,打开浏览器,访问http://127.0.0.1:9090或单击Launch Admin按钮,进行具体配置:

如果在此界面提示错误:log4j:ERROR setFile(null,true) call failed.
java.io.FileNotFoundException: C:\Program Files (x86)\Openfire\bin\..\logs\error.log (Access is denied)

请在安装完成后,设定以管理员权限运行openfire:

登陆或Launch Admin后,整个界面图如下:

左边可以看到相应的安装进度:

首先选择语言,按个人喜好来;接下来是服务器设置,如果没有特殊设定,可以使用default值;

数据库设置:可按服务器或项目配置设置相应的数据库,在此我们选择标准数据库以连接到目前我们项目同源的MySql数据库中;

 在数据库驱动选项选择MySql,然后修改数据库URL:jdbc:mysql://[host-name]:3306/[database-name] 为
jdbc:mysql://127.0.0.1:3306/openfire

数据库IP请填选正确的MySQL程序安装的服务器IP,openfire为数据库名(请提前在数据库中新建好openfire的DB);

用户名与密码请填写正确的MySQL用户名与密码;剩下的如果没有特殊要求可用默认值;然后在特性设置中,选用初始设置即可;

在设置管理员账户中,请填写好相应的密码并牢记,该密码即为初始admin的密码;

设置完成后,点继续会提示安装完成.

选择登陆到管理控制台,账号为admin,密码即为上面设置的管理员密码。

登录控制台,上传并安装在openfire官方网站下载的Presence Service插件presence.jar:

切换到服务器设置,对presenceservice插件进行设置,确保可允许任何人访问(如果是跨域浏览的话):记得要点击save button!

然后重启openfire。每次安装一个插件,最好都重启以使插件及其设置生效。

在重启之前,可以为openfire 设定环境变量 openfireHome 为openfire的安装目录:

同样安装下载到的broadcast插件:

可使openfire 具备对group或对所有用户广播message的功能。

安装broadcast插件之后,需在openfire 管理控制台的 服务器->服务器管理器->系统属性总增加以下属性设置(红色为必须设定,其他可选):

Property Key              属性值

plugin.broadcast.serviceName   broadcast

plugin.broadcast.disableGroupPermissions  true

plugin.broadcast.groupMembersAllowed  true.

plugin.broadcast.allowedUsers  the comma-delimitted list of users allowed to broadcast messages to all connected users at once. When this property isn't set, anyone is allowed to broadcast messages to all users. Users should be specified by their bare JID (e.g. john@myserver.com)

plugin.broadcast.all2offline  true.

plugin.broadcast.messagePrefix  (broadcast).

拖动右边滚动条到最下面,依次添加以上属性:

点击保存,确保属性保存成功:

也可以到网上搜索下载或自行开发更多的插件,对openfire的功能进行扩展。

1.4 Openfire Admin 功能

Openfire Server的admin功能也是通过插件方式提供的,可以从Openfire启动后在任务栏的图标

点击launchAdmin

或者直接输入openfire的安装网址和设定的访问端口(缺省为9090)来登录:

例如:http//10.139.8.167:9090

输入用户名和密码,即可登录到Openfire的管理控制台:

可以在这里完成对Openfire 服务器的各项设定,对Openfire用户/组及客户端会话的管理,也可进行分组聊天,发送广播及进行插件的安装。

FHWTVBox管理主要用到的用户群组管理功能有:

1.4.1 用户摘要:

1.4.2 组摘要:

1.4.3 用户组管理:

1.4.4 发送管理消息:

上述四项功能,已经完全在FHWTVBox Manager中实现,具体操作见后面FHWTVBoxManager的介绍。

二、TVBox Client 端APK开发

本项目的需求是要求在控制TVBox上的android系统启动后,自动在连接的TV上播放指定的网站视频内容。由于管理上的原因,不希望端用户改变访问的网站,所以此功能不能使用android 原生的browser来实现,必须自己开发一个开机自启动的应用,完成视频播放;然后,再开发一个服务器端的控制端,实现对TVBox Client端的播放内容的控制。在本项目中,我们使用Openfire push message的机制实现对TVBox的服务器端控制。

2.1 自启动Webview播放视频

2.1.1 自启动任务:

在android中建立一个自启动任务,是很简单的。首先,在AndroidManifest.xml文件中添加接收boot  complete系统广播消息的权限以及声明一个receiver:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

<receiver android:name=".BootReceiver">

<intent-filter>      <!-- 系统启动完成后会调用-->

<action android:name="android.intent.action.BOOT_COMPLETED"></action>

</intent-filter>

</receiver>

然后在工程文件中,建立那个receiver的Class文件:

这个receiver的任务很简单,就是接受到系统启动完毕的广播事件后,启动我们的应用activity。在这里就是TVActivity。

唯一值得注意的是,在android 4.0里面, 已经禁止了未经用户同意的自启动的应用。所以,一个自启动应用要能正常自启动,必须至少手工启动一次。这个TVBox应用需要设定一些数据,所以,在安装完毕之后,需要手工启动,完成设定之后才会真正成为自启动应用。

2.1.2 WebView 播放视频

利用WebView播放视频,最主要的是设定它的两个client WebViewClient:webView.setWebViewClient(new WebViewClient() {

public boolean shouldOverrideUrlLoading(

android.webkit.WebView view, java.lang.String url) {

view.loadUrl(url);

return true;

}

public void onPageFinished(WebView view, String url) {

super.onPageFinished(view, url);

// view.loadUrl("javascript: var v=document.getElementsByTagName('video')[0]; "+"v.play(); ");

}

public void onPageStarted(WebView view, String url, Bitmap favicon) {

super.onPageStarted(view, url, favicon);

}

});

和WebChromeClient:

webView.setWebChromeClient(new WebChromeClient() {

/**

* 显示自定义视图,无此方法视频不能播放

*/

private View myView = null;

private CustomViewCallback myCallback = null;

@Override

public void onShowCustomView(View view, CustomViewCallback callback) {

if (myCallback != null) {

myCallback.onCustomViewHidden();

myCallback = null;

return;

}

long id = Thread.currentThread().getId();

Log.v("WidgetChromeClient", "rong debug in showCustomView Ex: "

+ id);

ViewGroup parent = (ViewGroup) webView.getParent();

String s = parent.getClass().getName();

Log.v("WidgetChromeClient", "rong debug Ex: " + s);

parent.removeView(webView);

parent.addView(view);

myView = view;

myCallback = callback;

chromeClient = this;

isVideoPlaying = true;

}

public void onHideCustomView() {

long id = Thread.currentThread().getId();

Log.v("WidgetChromeClient", "rong debug in hideCustom Ex: "

+ id);

if (myView != null) {

if (myCallback != null) {

myCallback.onCustomViewHidden();

myCallback = null;

}

ViewGroup parent = (ViewGroup) myView.getParent();

parent.removeView(myView);

parent.addView(webView);

// added by Dumbbell Yang at 2012-12-04

webView.requestFocus();

myView = null;

}

isVideoPlaying = false;

}

});

还有其他一些WebView的设定需要调整。加载的网页内容有时候也需要调整。当然,不能忘记需要在AndroidManifest.xml文件中添加访问网络的权限:

<uses-permission android:name="android.permission.INTERNET"/>

2.2 登录Openfire并抓取群组数据

2.2.1 Openfire 登录设定

TVBox client端要能接收到Openfire Server端push过来的消息,必须能够登录Openfire Server并建立一个http 的长连接。为此,需要设定openfire server的IP及端口数据。另外,由于用户提出还要对TVBox进行群组管理,所以,还必须能够获取Openfire server上定义的用户群组的列表,供client端设定时选择。界面如下:

需要注意的是,这里的UserID和password,是抓取Openfire server用户群组列表的账号,这个账号必须具有管理员权限。这个设定及抓取动作只在安装完成后执行一次。真正Client每次启动后,连接Openfire server的账户,是用设定的TVBox名称作为前缀,加下划线加TVBox的device ID作为账号,IP Addressz作为名词,固定密码自动注册,然后自动登录的,由于需要获取Client端的IP Address,所以还需要在AndroidManifest.xml文件中添加权限:

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

2.2.2 Openfire登录及数据抓取

利用设定的管理员账号和密码,登录Openfire,是通过WebView的load url功能实现的:

webView.loadDataWithBaseURL(null, util.getOpenfireAutoHTML("http://" + strServer + ":9090", strUserName, strPassword), "text/html", "utf-8", null);

其中getOpenfireAutoHTML 方法根据Openfire Server IP,账号和密码构造一个自动登录的HTML页面,然后在WebView中加载,完成登录Openfire的功能。具体实现方法,可见代码。

然后,在WebView中实现JavaScript与WebView内容的交互。

首先定义JavaScript interface:

/* An instance of this class will be registered as a JavaScript interface */

class MyJavaScriptInterface   {

@SuppressWarnings("unused")

public void loadGroup(String html) {

//System.out.println(html);

//System.out.println("Extract Groups:");

List<Link> groups = util.extractOpenfireGroups(html);

if (groups.size() > 0){

notGetGroups = false;

String[] arrGroup = new String[groups.size()];

int i = 0;

for(Link group:groups){

Log.i(TAG, "Group:" + group.getText() + "," + group.getRef());

arrGroup[i++] = group.getText();

}

cmbGroups.setSuggestionData(arrGroup);

showGroupMessage(arrGroup.length);

}

}

@SuppressWarnings("unused")

public void add2Group(String html) {

//System.out.println(html);

if (html.indexOf("success") != -1){

notAdd2Group = false;

System.out.println("add to Group Success!");

}

}

//added by Dumbbell Yang at 2013-02-28

//取得用户所在group的admin账号,和他建立chat

@SuppressWarnings("unused")

public void getGroupAdmin(String html) {

//System.out.println("Get Group Admin:" + html);

TVBox.adminUsers = util.extractHTMLPageAllAdminUsers(html);

if (TVBox.adminUsers.size() > 0){

notGetGroupAdmin = false;

System.out.println("got Group Administrator!");

showGroupAdminMessage(TVBox.adminUsers.size());

}

else{

System.out.println("Not got Group Administrator!");

}

}

}

然后,在WebView的WebViewClient中,增加方法:

public void onPageFinished(WebView view, String url) {

super.onPageFinished(view,url);

/* This call inject JavaScript into the page which just finished loading. */

//从加载的session-summary.jsp页面的内容中提取Openfire用户

if (url.endsWith("group-summary.jsp") && notGetGroups){

webView.loadUrl("javascript:window.HTMLOUT.loadGroup('<head>'+document.getElementsByTagName('html')[0].innerHTML+'</head>');");

}

//added by Dumbbell Yang at 2013-02-28

else if (url.indexOf("group-edit.jsp") != -1 && notGetGroupAdmin){

webView.loadUrl("javascript:window.HTMLOUT.getGroupAdmin('<head>'+document.getElementsByTagName('html')[0].innerHTML+'</head>');");

}

else if (url.indexOf("group-edit.jsp") != -1 && notAdd2Group){

webView.loadUrl("javascript:window.HTMLOUT.add2Group('<head>'+document.URL+'</head>');");

}

}

在WebView中的页面加载完成后,依次执行loadGroup 获取群组列表;getGroupAdmin,获取群组所有的管理员(因为用户要求可以有多个管理员同时来控制Client端,所以,每个group的管理员账号可能有多个);add2Group 把自动注册的client用户加入群组。

上面三项功能都是通过解析WebView加载完成后的HTML page内容的方式完成的。具体实现方法,可见代码。当获取用户群组数据后,效果图如下

在这里选定一个群组,设定TVBox名称前缀及缺省打开的网站URL,单击保存,完成设定。

2.3 Openfire自动注册登录并加入群组

第一次启动TVBox Activity,会进入2.2的Settings Dialog,完成设定后,进入TVBox Activity,创建XMPP connection,自动注册openfire账号,加入设定的群组,自动登录,并和群组的管理员建立chat,并对chat设定message listener,监听管理员发来的信息,达到Server端对Client的控制。

2.3.1 Openfire自动注册登录

自动注册登录的流程大致如下代码所示:

// added by Dumbbell Yang at 2012-11-20

new Thread(new Runnable() {

@Override

public void run() {

if (createXMPPConnection()) {

String username = getTVBoxName();

if (autoRegister(username, XMPPPassword)) {

if (autoLoginToOpenfire(username, XMPPPassword)) {

addChatListener();

}

}

}

}

}).start();

具体实现可见代码。要注意的是,在android 4.0中,已不允许同步访问网络;另外,由于android的线程现在,所以,这些注册登录动作最好都另起线程来做。最后的结果,需要更新界面的话,如下使用给handler发消息的方式:

browseHandler = new Handler() {

// @Override

public void handleMessage(android.os.Message msg) {

// TODO Auto-generated method stub

// browseURL();

if (msg.what == LOADING) {

browseWebView();

}

else if (msg.what == REFRESH) {

Message message = (Message)msg.obj;

refreshWebView(message.getBody(),message.getFrom());

//refreshWebView(msg.obj.toString());

}

}

};

browseHandler.sendEmptyMessageDelayed(LOADING, 5000);

2.3.2 加入群组并建立消息监听

登录成功后,加入群组,是采用在settings dialog中加载相应web 页面,并同过javascript interface,解析WebView的HTML内容方式完成的:

// add current user into group

String strGroup = prefs.getString(SettingsDialog.GROUP,FHWTVBOX_GROUP);

String strServer = prefs.getString(SettingsDialog.SERVER,XMPPHost);

if (isAdd2Group == false) {

mDialog.addUserToGroup(strServer, xmppConn.getUser(),strGroup);

}

获取群组的admin 账号列表:

mDialog.getGroupAdminUserList(strServer,

prefs.getString(SettingsDialog.USERNAME, FHW_ADMIN),

prefs.getString(SettingsDialog.PASSWORD, FHW_ADMIN_PASSWORD), strGroup);

然后和dmin及群组的所有admin账号建立chat并监听chat message:

createChatListener(cm, FHW_ADMIN + "@" + xmppConn.getServiceName());

// added by Dumbbell Yang at 2013-02-28 和Group里的每个admin都建立聊天

if ((this.adminUsers != null) && (this.adminUsers.size() > 0)) {

for (String adminUser : this.adminUsers) {

createChatListener(cm,adminUser + "@" + xmppConn.getServiceName());

}

}

下面是createChatListener的代码:

private void createChatListener(ChatManager cm, String strChatUser) {

cm.createChat(strChatUser, null);

cm.addChatListener(new ChatManagerListener() {

@Override

public void chatCreated(Chat chat, boolean able) {

chat.addMessageListener(new MessageListener() {

@Override

public void processMessage(Chat chat, Message message) {

String strMessage = message.getBody();

Log.i(TAG, "received message:" + strMessage + " from "

+ message.getFrom());

if (strMessage != null) {

android.os.Message msg = browseHandler

.obtainMessage();

msg.what = REFRESH;

msg.obj = message;//strMessage;

msg.sendToTarget();

}

}

});

}

});

}

接收到消息时,会调用前面handler里面refreshview的方法,切换WebView的内容到消息指定的网页。

至此,client端的开发就完成了。

三、FHWTVBox Manager 开发

要对Client端的TVBox进行控制,还必须得有Server端的程序。FHWTVBox Manager是一个桌面的Java Application,实现了对TVBox的控制功能,安装了jre就可以运行,最新程序可以从本机openfire的安装网站下载,路径通常为:

http//10.139.8.167:9090/FHWTVBoxManager.jar

3.1 界面及功能

在浏览器中输入上面的地址,下载FHWTVBox Manager到本地,双击打开,界面如下:

最上面是openfire server的各项设定,输入openfire各项设定及管理员用户名和密码,后单击登录按钮,就会登录到openfire  server,把用户及群组信息抓取出来:

中间有群组管理和机顶盒管理两个Tab:

3.1.1 群组管理

群组管理中,列表显示openfire上所有的用户(也就是FHWTVBox),绿色为online,灰色为offline。选择群组下拉框显示里openfire server 上目前所有的用户群组,最低部的FHWTV 频道下拉框显示了从指定网站抓取的所有电视频道,可用于发送切换消息。

可以使用新增,更新和删除按钮,管理openfire server上的用户群组。

可以使用加入和移除按钮,将选定的用户加入指定的群组或从其中移除。

也可以在此删除选中的TVBox。

3.1.2 机顶盒管理

机顶盒管理界面如下:

er的数据。

3.2.1 Java Swing组件

在开发中主要用到了JTree和JList两种组件,用来显示TVBox的群组树状结构及列表结构。其数据Adapter是参考网上的代码修改而成,比较简单,在此不再赘述。

3.2.2生成可执行jar

生成可执行jar的方法网上也有很多数据可供参考,也一并略过。

3.2.3 HttpClient获取及操作openfire 数据

此处利用的是apache 开源的HttpClient 3.0.1的版本,最新的4.0的版本改动比较大,需要注意。

首先是用户点击login之后,createXMPPConnection成功,并调用autoLoginToOpenfire 登录一个管理员账号到Openfire,做好对client端发消息的准备,并建立一个PacketListner,接收Client对push的回馈:

private void addMessageListener(){

System.out.println("addMessageListener");

//添加chat message listener

PacketFilter filter = new MessageTypeFilter(Message.Type.chat);

xmppConn.addPacketListener(new PacketListener() {

public void processPacket(Packet packet) {

Message message = (Message) packet;

System.out.println("Got message");

具体实现请参见详细代码。

然后调用fillTVBoxes方法,使用httpClient,去抓取openfire的用户信息,群组信息,在线用户信息等,填充JList和JTree及群组combox。以后每次openfire群组及用户数据有改变, 都会重新调用fillTVBoxes方法,刷新显示数据。

在fillTVBox中,使用httpClient抓取数据,示例如下:

首先判断是否已经有session:

//如果已有cookie,直接GET

if (sessionID.equals("") == false){

return getURLContent(client, strServerPort + "/" + strURL);

}

//否则

//使用POST方法

PostMethod postMethod = new PostMethod(strServerPort + "/login.jsp"){

@Override

public boolean getFollowRedirects(){

return true;

}

};

然后,构造需要提交的数据:

/**

* 使用POST方式提交数据

*/

NameValuePair[] loginInfo = {

new NameValuePair("url",strServerPort + "/" + strURL),

new NameValuePair("login","true"),

new NameValuePair("username",strUserName),

new NameValuePair("password",strPassword),};

postMethod.setRequestBody(loginInfo);

提交数据后,处理返回值并解析:

String info = null;

try {

client.executeMethod(postMethod);

if (sessionID.equals("")){

Cookie[] cookies = client.getState().getCookies();

for (int i = 0; i < cookies.length; i++) {

Cookie cookie = cookies[i];

if (cookie.getName().trim().equalsIgnoreCase("JSESSIONID")){

sessionID = cookie.getValue().trim();

}

}

}

int code = postMethod.getStatusCode();

//System.out.println("Status:" + code);

if (code == HttpStatus.SC_OK){

info = new String(postMethod.getResponseBodyAsString());

}

如果调用返回的数据不为空,则调用不同的方法解析出所需要的值,可能会用到正则表达式,例如:

extractFHWTVChannels 解析出指定的URL web 页面上能够播放的TV频道的URL;

extractOpenfireOnlineUsers解析出所有online的openfire user lis;

extractOpenfireUsersInGroup解析出某一个openfire group所包含的user list。

这些都是通过构造不同的post 数据,利用httpClient提交到相应的页面,然后解析返回的HTML内容的方式完成的。

对用户群组数据的操作同样也是利用httpClient,提交不同的post数据到指定页面来完成的。例如增加用户到群组:

public static String addOpenfireUserToGroup(HttpClient client,

String strServerPort, String strUserName, String strGroupName){

//使用POST方法

PostMethod postMethod = new PostMethod(strServerPort + "/group-edit.jsp?group=" + strGroupName);//{

//      @Override

//      public boolean getFollowRedirects(){

//          return true;

//      }

//  };

/**

* 使用POST方式提交数据

*/

NameValuePair[] postInfo = {

new NameValuePair("group", strGroupName),

new NameValuePair("add", "Add"),

new NameValuePair("username", strUserName),

new NameValuePair("addbutton", "添加"),};

postMethod.setRequestBody(postInfo);

String info = null;

try {

client.executeMethod(postMethod);

int code = postMethod.getStatusCode();

//添加成功,会跳转,添加失败,则不跳转

if (postMethod.getResponseHeader("location") == null){

return "Faield!";

}

String strRedirectURL = postMethod.getResponseHeader("location").getValue();

if (code == HttpStatus.SC_OK){

info = new String(postMethod.getResponseBodyAsString());

}

else if (strRedirectURL.endsWith("/group-edit.jsp?group=" +

strGroupName + "&success=true")){

return "success";

}

}

catch (HttpException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

finally {

postMethod.releaseConnection();

}

return info;

}

其他删除群组用户,增加群组,修改群组,删除群组代码逻辑完全类似。

四、FHWTVBox Client和FHWTVBoxManager整合应用

4.1 FHWTVBox Client端安装设定

FHWTVBox Client端是一个运行在android 4.0.3平台上的apk,可以从以下网址下载安装:。

http://10.139.8.167:9090/FHWTVBox.apk

安装完毕后,单击打开或者重新启动,程序界面如下,首先出现设定界面(此为仿真器所截取的竖屏,在TVBox上为横屏,内容一致):

输入openfire  server的ip,端口,service及管理员的用户名和密码,系统会去抓取openfire、 server上已建立的用户群组,显示在下面的下拉框中,供用户选择:

选择一个当前TVBox要加入的群组,输入TVBox的名称前缀(TVBox命名为前缀_设备ID),以及TVBox启动后打开的缺省网站地址:

单击保存,就会自动注册用户到openfire  server,加入到选择的群组,并进入预设的网站:

4.2 FHWTVBoxManager 管理操作

此时,打开FHWTVBox Manager,登录成功后,可以看到有三个用户在线:(admin,一个测试TVBox,一个仿真器):

此时可以在列表中选中相应的TVBox,进行删除。

删除完成,系统会给出提示:

点击确定,可看到刚才选择的TVBox已经不见了:

切换到机顶盒管理Tab,选择仿真器及测试TVBox,选择湖南卫视,发送切换消息:

在Manager上会得到频道切换成功的消息:

点击确定后,展开群组,可以看到频道已经切换:

由于仿真器缺少播放视频所需的硬件支持,所以虽然频道已经切换,但内容无法播放。

频道切换的实际效果在测试TVBox上可以看到。

五、android版FHWTVBox Admin

前面开发的FHWTVBoxManager是一个PC端的TVBox的管理工具,必须在计算机上完成。后来用户提出要把管理功能在手机实现,于是,就有了FHWTVBox Admin。这是一个可以运行在android设备(android智能手机或TVBox机顶盒)上的FHWTVBox的管理工具。安装路径与FHWTVBox android client端一样,只是apk名称不同:

http://10.139.8.167:9090/FHWTVBoxAdmin.apk

安装完成后,界面如下所示(手机和仿真器上是竖屏,机顶盒上是横屏,但内容一致):

FHWTVBoxManager一样,也是分了三个Tab,服务器设定,群组管理和机顶盒管理。功能也和HWTVBoxManager类似。在服务器设定tab输入openfire 服务器相关设定及登录用户名密码后,点击登录,会登录到openfire server上,抓取所有群组,机顶盒用户及在线机顶盒信息,填充在群组管理和机顶盒管理的列表中:

在这个界面上,可以和FHWTVBoxManager一样,进行群组增删改,把机顶盒用户加入群组或从群组中移除,以及删除机顶盒用户等操作。操作完成后,系统会给出提示信息并刷新显示数据。

可以在机顶盒管理 Tab进行机顶盒频道切换的消息发送操作:

和FHWTVBoxManager同样操作,先选中要切换频道或发送信息的机顶盒,然后在频道下拉选框中选择频道,然后频道的网址就会显示在推送消息的输入框中(如果要发送消息,可以在此直接输入),点击发送按钮,就会把相应的内容推送到选中的机顶盒中。机顶盒成功接收消息或切换频道后,会回送一个消息通知,显示在FHWTVBoxAdmin的状态区:(手机及仿真器在顶部,FHWTVBox机顶盒在底部)

点击状态区的消息通知,可以查看消息的内容。点击之后,消息通知就自动关掉了。

FHWTVBox admin所用到的开发技术,android的界面显示有ExpandableListView和checkable的listView,都是很简单的,其余获取及操作Openfire的数据,和PC上的FHWTVBoxManager一样,是通过httpClient进行的,代码几乎都完全一样,在此不再赘述。

六、FHWTVBox Openfire Plugin JSP

本来到这里项目开发已经可以结束了,但可惜用户的需求是永无止境的。Android手机上可以管理TVBox了,那么iPad上呢?iPhone上呢?这一来,我就不得不考虑采用plugin JSP的方式来开发这个TVBox的管理平台了。虽然这样界面体验在移动端不是很好,但是作为管理应用,功能实现才是首要目标。所以才有了TVBox plugin

6.1 TVBox JSP Plugin插件及部署

TVBox plugin是一个可以运行在openfire Server上的插件,用JSP的形式实现了FHWTVBoxManager的全部功能:TVBox组添加修改删除,TVBox加入组或从组中移除,TVBox删除,TVBox消息推送以及TVBox回复消息显示及TVBox消息推送历史记录。这个插件JSP可以从PC浏览器或android平台浏览器或IOS平台的浏览器访问,实现了移动Web形式的通用TVBox管理平台,可以使用电脑或android平板,anroid手机,机顶盒或iPhoneiPad等等任一支持http浏览的终端上访问。

    插件部署步骤:

    1.       复制tvbox.jar插件安装包到openfire的安装目录下的plugins目录。

重新启动openfire,会看到如下包含hello,TVBox Plugin!的提示:

openfire的安装目录下的pluginstvbox目录下的Web文件夹中,发现tvbox.htm:

 2.   openfire的安装目录下的pluginsadmin目录的webapp下。

登录openfire服务器后,在插件tab中能看到如下FHWTVBox Plugin的条目:

6.2 TVBox Plugin登录及使用

要访问插件jsp,可以在浏览器中输入http://10.139.8.167:9090,登录openfire后,点击用户/tab,选择富鸿网机顶盒项目;也可以在浏览器中直接输入http://10.139.8.167:9090/tvbox.htm

登录后直接转到用户/组tab的富鸿网机顶盒项目的消息推送页面:

其中tvboxclient_c22b13562afa5c05是测试用机顶盒,test是电脑上登录spark端用户,绿色图标表示在线,灰色图标表示离线。

6.2.1 发送消息

在这里,可以选择频道:

然后选中要推送消息的机顶盒:

单击发送后,系统就会推送消息到选择的机顶盒,切换机顶盒播放频道:

并将页面自动转到查看机顶盒回复的页面:

而PC上的Spark登录用户,则会收到一条消息通知:

6.2.2查看回复

 

在消息历史页面,可以查询某段时间内推送到某些机顶盒上的消息:

输入机顶盒部分或全部ID,选择起止时间:

点击搜索,可看到如下搜索结果,包括消息推送时保存在数据库的所有栏位: 

6.2.3 机顶盒管理

而在机顶盒管理页面,可以和FHWTVBoxManager中一样,完成TVBox群组的增加修改和删除,完成机顶盒加入群组,从群组移除及删除机顶盒功能,界面如下所示:

机顶盒管理的功能和操作步骤和FHWTVBoxManagerFHWTVBox Admin都是基本一致的,同样可以把TVBox加入群组,从群组中移除,对群组增删改查及删除TVBox

上图同样显示的是openfire server是定义的群组。

6.3 TVBox Plugin开发

要进行Openfire plugin的开发,首先必须下载openfire 的源码,并进行部署编译,然后安装官方的文档,增加自己的plugin的配置文件及代码,最后编译成jar檔,放在openfire的安装目录下的plugins目录。

6.3.1 Openfire源码部署及设定

可以从http://www.igniterealtime.org/downloads/source.jsp下载打包的openfire 的最新source code ,解压到本地目录,例如:F:\Openfire Software\openfire_src_3_7_1      

或者使用svn http://svn.igniterealtime.org/svn/repos/openfire/trunk checkout整个openfire 项目到同样的本地目录。

然后在Eclipse中,新建Java Project,根据Eclipse版本不同,操作有点差别。

Eclpse Europa 3.3.2版早期版本,如下图勾选' create project from existing source' 浏览到解压的openfire 源码目录下的'openfire_src' ,完成创建(网上很多openfire源码部署都是这样写的,可是我在我的Eclpse上怎么也找不到那个' create project from existing source'的勾选框,后来才知道是Eclipse的版本升级啦):

而对于我正在使用的Eclipse indigo 3.7.0版,则界面如下:不要选择use default location,然后点击浏览,选择Openfire source code本地目录,完成工程创建。

然后右键项目 --> BuildPath -->Configure BuildPath-->library --add jars openfire下所有的lib 及其子目录中的jar包都添加到进来,把插件中的lib目录下的jar 包添加进来。

接下来配置运行参数,Run::Open Run Dialog... menu.

或者 Run -- Run configuration

选择Java Application 右键新建一个Java application 重新命名为openfire

选择刚才建的项目openfire371

设定Main class:(search) org.jivesoftware.openfire.starter.ServerStarter

单击 Arguments 选框

VM-Arguments 键入 -DopenfireHome="${workspace_loc:openfire}/target/openfire"

此处实际上是告诉 openfire ,openfireHome 在什么地方,用于eclipse执行

java命令时传递的参数,openfire程序可以通过System.getProperty("openfireHome")得到 openfire的本地位置。

点击classpath 选项 User entries --->Advanced-->Add Folder---> OK添加以下三目录

Openfire371::src::i18n

Openfire371::src::resources::jar

Openfire371::build::lib::dist

点击Common tab

勾选 DebugRun复选框

6.3.2 Openfire源码编译

现在可以使用源码中自带的ant脚本,对Openfiresource code进行编译了。

选择openfire371 project, 选择EclipseTools菜单window –> Show View -> Ant

就会在右边ant页面列出所有openfire中预定义的编译任务:

ant view里面双击openfire(default),开始编译,编译成功,界面如下:

如果编译不成功,请检查相关配置及jar文件,确保编译成功,才可以进行下一步plugin的开发。

6.3.3 Openfire plugin 代码结构

根据openfire官方的plugin develop guide:

http://www.igniterealtime.org/builds/openfire/docs/latest/documentation/plugin-dev-guide.html

openfire plugin 的代码结构如下:

其中,plugin.xml是必须的plugin的定义文件,其中定义了plugin的配置信息以及包含的页面信息。如下图是TVBox plugin的定义文件:

其中class定义了plugin的包含包名在内的主类(似乎必须是定义在org.jivesoftware.plugin 包内);

databaseKey定义了plugin要执行的数据库SQL脚本文件,如果在plugin中需要建立table的话,就要准备这份文件,按数据库类型命名放在如下的目录:

然后下面的<adminconsole>部分指定了pluginopenfire 服务器控制面板访问时的路径。<tab id="tab-users">表示放在用户/tab下:

如果是<tab id="tab-server">则表示放在服务器 tab下。要放入其他tab,相应的id可以在openfire源码自带的plugin的定义文件中查找。

<sidebar id="sidebar-tvboxes" name="${users.sidebar.tvboxes.name}" 表示plugin

/” tab下子tabid和名字,其中${users.sidebar.tvboxes.name}是采用多语言资源文件的方式,取资源文件中key users.sidebar.tvboxes.name的相应值:

中文的资源文件如下图,文字都被变成了unicode编码。开始我还以为要去一个字一个字查找其unicode编码,后来才发现在英文资源文件(编码设定为ISO-8859-1)中,直接输入中文,就会自动转换为unicode编码,然后直接copy到中文资源文件(编码UTF-8)就可以了。

<sidebar id="sidebar-tvboxes" 下面的每一个item,都定义了一个jsp页面,这里才是plugin的核心内容。

例如发送消息页面定义如下:

<item id="push-message" name="${tvbox.item.pushmessage.name}"

         url="push_message.jsp" description="${tvbox.item.pushmessage.description}" />

id是页面的标识,url是页面的名称,namedescription是资源文件里面的key

这里定义有多少个item,这个plugin里面就包含有多少个jsp页面。

Plugin里面的jspweb资源,被放在在web目录中:

其中,WEB-INF下的web-custom.xml,是用来定义plugin中用到的Servlet的。在TVBox插件中并没有用到。

web目录下的其他活页夹,imagesscriptsstyle和一般的web应用是一样的,用来存放图片,javascript脚本以及css文件。

到这里,已经基本上把一个插件源代码的主要结构讲解完毕了,现在总结一下:

readme.xmlplugin的自述说明文件

changelog.htmlplugin的发布日志文件。

logo_large.pnglogo_small.pngplugin显示在openfire 插件列表中的图标文件。

plugin.xmlplugin的定义文件,前面已经详细讲过。

 

database目录是用来存放plugin中用到的数据库创建tablesql脚本文件。

I18n目录是用来存放plugin中用到的多语言资源文件。

lib目录是用来存放plugin中引用的的第三方library

web 目录是用来存放plugin中用到的jsp页面,servlet定义及其他web资源。

Java目录中存放的是plugin中用到的所有java code。(openfire source code中的plugin源码中都是java,但是在官方的plugin结构中改为了classes,可能以后会有变化)。

6.3.4 Openfire plugin Class开发

下面我们来看如何进行Openfire plugin Class的开发。一共包含如下8Class:

public class TVBoxPlugin implements Plugin

public class EchoInterceptor implements PacketInterceptor

public class EchoMessage extends Message

public class LinkItem

public class ServletUtil

public class TVBoxBean

public class TVBoxMessage

public class TVBoxServlet extends HttpServlet

首先是创建在plugin.xml文件中定义的plugclass并实现plugin接口,保持包名和类名一致。在这里就是org.jivesoftware.openfire.plugin.tvbox.TVBoxPlugin,如下图所示:

其实,在这个plugin的主类TVBoxPlugin中,能做的事并不多。

首先,定义了一个回报消息的拦截器,并在plugin初始化时将其加入统一的拦截器管理器中。代码如下:

public class TVBoxPlugin implements Plugin{

private EchoInterceptor echoInter = null;

@Override

public void initializePlugin(PluginManager manager, File pluginDirectory) {

System.out.println("hello,TVBox Plugin!");

echoInter = new EchoInterceptor();

InterceptorManager.getInstance().addInterceptor(echoInter);

}

plugin初始化时做的另一件事就是在控制台输出TVBox Plugin的初始化信息,在前面openfire server console启动界面截图中可以看到。

然后是重载的一个plugin销毁时的方法:

@Override

public void destroyPlugin() {

System.out.println("TVBox Plugin Destroyed!");

if(echoInter != null){

echoInter.closeDB();

InterceptorManager.getInstance().removeInterceptor(echoInter);

}

}

输出控制台信息,并关闭DB,移除回报消息拦截器。

其他方法都是对拦截器的方法做了一次封装,让用户可以通过plugin对象直接去操作消息拦截器里面定义的保存消息,查询消息的方法。代码如下:

public void setSendID(long value){

echoInter.setSendID(value);

}

public List<EchoMessage> getEchoMessage(){

return echoInter.getEchoMessage();

}

public List<TVBoxMessage> searchTVBoxMessage(String sendTo, long sendTimeFrom, long sendTimeTo){

return echoInter.searchTVBoxMessage(sendTo, sendTimeFrom, sendTimeTo);

}

public void saveTVBoxMessage(TVBoxMessage msg){

echoInter.saveTVBoxMessage(msg);

}

第二个ClassEchoInterceptor,实现了openfire预定义的PacketInterceptor接口,负责在plugin里对接收到的回报消息进行处理。

首先是定义消息列表和sendID以及数据库操作的SQL语句。

private List<EchoMessage> echoMessage = new ArrayList<EchoMessage>();

private long sendID = -1;

private static final String CREATE_TVBOXMESSAGE =

"INSERT INTO ofTVBoxMessage (sendID, sendFrom, sendTo, message, sendTime) " +

"VALUES (?, ?, ?, ?, ?); ";

private static final String RECIEVE_ECHOMESSAGE =

"UPDATE ofTVBoxMessage SET echoTime = ? WHERE sendID = ? AND sendTo = ? ;";

private static final String SEARCH_TVBOXMESSAGE =

"SELECT * FROM ofTVBoxMessage WHERE sendTo LIKE ? AND sendTime >= ? AND sendTime <= ? ORDER BY sendTime DESC;";

private static Connection con = null;

主要方法是重载的interceptPacket方法,对接收到的chat message进行保存。

@Override

public void interceptPacket(Packet packet, Session session,

boolean incoming, boolean processed) throws PacketRejectedException {

// TODO Auto-generated method stub

if(!processed && packet instanceof Message){

if(incoming && Type.chat == ((Message)packet).getType()){

//System.out.println("Chat echo " + packet.toString());

EchoMessage curMsg = new EchoMessage((Message)packet);

echoMessage.add(curMsg);

recieveEchoMessage(curMsg);

}

}

}

这个类里的其他方法还包括保存和查询回报消息。在plugin主类中已有调用,这里是其具体实现的地方。代码比较简单,不再赘述。

第三个ClassEchoMessage,对openfire预定义的message类进行扩展,增加了sendIDrecieveDate两个属性。

第四个ClassLinkItem,封装了从HTML 内容中解析出来的超链接对象。

第五个ClassServletUtil,定义了一些公用方法。

第六个ClassTVBoxBean,定义了对openfire用户和群组数据的操作。

第七个ClassTVBoxMessage,定义了对应数据库保存的EchoMessage的实体类。

第八个ClassTVBoxServlet,扩展子HttpServlet,定义了Plugin中用到的需要用Servlet完成的功能。

6.3.5 Openfire plugin JSP开发

TVBox plugin里主要包括以下四个JSP页面,以后可能还会增加。每个jsp页面首先在plugin.xml中有定义,sidebar中的每一个Item都对应一个JSP页面:        

<sidebar id="sidebar-tvboxes" name="${users.sidebar.tvboxes.name}"

description="${users.sidebar.tvboxes.description}">

<item id="push-message" name="${tvbox.item.pushmessage.name}" url="push_message.jsp" description="${tvbox.item.pushmessage.description}" />

<item id="client-echo" name="${tvbox.item.clientecho.name}" url="client_echo.jsp"

description="${tvbox.item.clientecho.description}" />

<item id="message-history" name="${tvbox.item.messagehistory.name}" url="message_history.jsp"

description="${tvbox.item.messagehistory.description}" />

<item id="tvbox-manager" name="${tvbox.item.tvboxmanage.name}" url="tvbox_manage.jsp"

description="${tvbox.item.tvboxmanage.description}" />

</sidebar>

下面以PushMessaget.jsp为例,讲解一下如何进行JSP的开发。(其实可以首先从source code所带插件中复制一个功能相近或相关的JSP过来,修改成自己需要的就好了。)

JSP最开始的<%@ page import 部分无需多说,上一步class开发中写的class用到的都需要在此导入。

下来的两行引用了标准的Taglib,用于多语言处理,从前面定义的资源文件中提取字符串。

<%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c" %>

<%@ taglib uri="http://java.sun.com/jstl/fmt_rt" prefix="fmt" %>

接下来三行是:

<jsp:useBean id="webManager" class="org.jivesoftware.util.WebManager"  />

<jsp:useBean id="boxBean" class="org.jivesoftware.openfire.plugin.tvbox.TVBoxBean"  />

<% webManager.init(request, response, session, application, out );

定义了两个JavaBean,一个是Openfire预定义的,一个是自己写的,并照例对webManager bean进行了初始化。

然后的java代码主要是获取所有的频道数据,openfire用户组和在线用户数据。

List<LinkItem> tvChannels = new ArrayList<LinkItem>();

tvChannels = boxBean.getFHWTVChannels("http://tv.lh.efoxconn.com/channel.htm");

List<String> groups = boxBean.getAllGroups();

List<String> onlineUsers = boxBean.getOnlineUsers();

随后是处理页面提交的代码,获取用户选择的TVBox以及输入的信息,或者选择的频道,发送消息到TVBox,并在页面显示结果消息。其中调用plugin中的saveTVBoxMessage方法对消息进行了保存:

String strMessage = request.getParameter("message");

String strSendTo = request.getParameter("tvboxes");

List<String> selectedBoxes = new ArrayList<String>();

String strSendResult = "消息发送结果:";

boolean isMessageSent = false;

if ((strMessage != null) && (strSendTo != null)){

SessionManager sessionManager = webManager.getSessionManager();

PresenceManager presenceManager = webManager.getPresenceManager();

UserManager userManager = webManager.getUserManager();

String[] users = strSendTo.split(",");

for(int i = 0;i < users.length;i ++){

selectedBoxes.add(users[i]);

}

String serverDomainName = XMPPServer.getInstance().getServerInfo().getXMPPDomain();

// Get handle on the TVBox plugin

TVBoxPlugin plugin = (TVBoxPlugin)XMPPServer.getInstance().getPluginManager().getPlugin(

"tvbox");

long sendID = ServletUtil.getCurrentID();

plugin.setSendID(sendID);

for(int i = 0;i < users.length;i ++){

//由于选择TVBox会自动选择器群组,所以发送消息时需将群组剔除

if (groups.contains(users[i]) == false){

try{

sessionManager.sendServerMessage(new JID(users[i] + "@" + serverDomainName), null, strMessage);

long sendTime = ServletUtil.date2long(new Date());

TVBoxMessage msg = new TVBoxMessage();

msg.setSendID(sendID);

msg.setSendFrom("admin@" + serverDomainName);

msg.setSendTo(users[i] + "@" + serverDomainName);

msg.setMessage(strMessage);

msg.setSendTime(sendTime);

plugin.saveTVBoxMessage(msg);

strSendResult += "<br />发送到 " + users[i] + " 成功!";

}

catch(Exception e){

strSendResult += "<br />发送到 " + users[i] + " 失败 for !" + e.toString();

}

}

}

isMessageSent = true;

}

else{

strMessage = "";

}

strSendResult = new String(strSendResult.getBytes("ISO-8859-1"),"utf-8");

下面都是HTML的内容了。

首先是HTMLhead,其中包含的pageID就是在plugin.xml中定义过的,<fmt: 是调用标

Taglib引用资源文件,其中的相对目录都是位于plugin 代码目录的Web活页夹下:

<html>

<head>

<title><fmt:message key="tvbox.pushmessage.title"/></title>

<meta name="pageID" content="push-message"/>

<link rel="stylesheet" type="text/css" href="style/treelistcontrol.css">

<script language="JavaScript" type="text/javascript"  src="scripts/treelistcontrol.js"></script>

随后的JavaScript代码中,构造了显示TVBox群组用户的树型结构以及页面交互的响应函数,并且通过javascript定时函数,实现在消息发送成功之后,延时三秒,自动转向回报信息页面client_echo.jsp,可以查看到Client端接收消息后的回馈信息。

    其他几个JSP页面大体相同,唯一值得注意的是引用的imagesjavascript等等web资源,都要用相对路径,放在web下的相应目录中。然后就是多参照source code中附带的其他plugin里面的类似功能的代码,依葫芦画瓢就可以啦。

    到这里,tvbox插件的所有东东都齐备了,整个源码位于openfire371项目下的src目录下的plugins里面,目录结构如下:

开发工作至此大功告成,接下来就是编译plugin,生成jar档,然后按前述方法部署就可以了。

Openfire 的源码工程里,Ant view中预先定义了许多build任务,如前面build源码是运行的openfire(default)Build plugin可以运行其中的pluginsbuild所有plugin;或者plugin,仅build某一个指定的plugin,比如TVBox,专门用来build自己开发的这一个TVBox plugin

EclipseWindow 菜单,选择Show View  ->  Ant,就会在右边列出openfire source code源码工程中预定义的Openfire XMPP Server build task列表。

然后向下拖动,右键选中其中的plugin->   Run As   ->  External Tools Configurations…

Arguments中输入:-Dplugin=tvbox,其中tvbox就是你的pluginsrc目录下的源码目录名称。

Run,运行build task,如果Eclipse Console输出有编译错误,请修改java classjsp page,保证最终build successful

成功编译后,生成的plugin插件可以在target目录下的plugins中看到:

七、FHW TVBox按群组管理

前面实现的FHW TVBox的管理功能,使用一个admin账号去管理所有的TVBox。当TVBox很多时,可能会出现不同的组需要由不同的管理员来管理这中需求。

为实现这一需求,首先,要在openfire server上注册管理员用户(新增用户,勾选最下面的Is Administrator 选择框):

这样创建的用户都具有管理员权限,登录到openfire server上,能够查看到所有群组中的TVBox。如果没有勾选这个选项,将不能看到其它的群组。

然后,在编辑用户组 Tab的编辑组界面:

将这个管理员用户加入被它管理的群组:

这样,在FHWTVBoxManager中,admin登录后,就只能看到它能够管理的用户组了:

(如果一个管理员需要管理多个组,可以把他加入多个组中。)

FHWTVBox client 程序已经修改,client在登录openfire server后,除了与缺省admin建立连接外,还会与同组内的所有具有管理员权限的账号建立连接(在前面的代码示例中可以看到)。这样,除了admin账号仍然可以管理外,所有与client账号同在一组的具有管理员权限的账号,都可以使用push message的方式对这个TVBox进行管理了。

本博客中相关工程源码可到CSDN下载:

http://download.csdn.net/detail/yangdanbo1975/5825753

转载于:https://www.cnblogs.com/dumbbellyang/archive/2013/06/02/3114328.html

基于 OpenFire 的TVBox管理平台开发笔记相关推荐

  1. 基于java安防管理平台计算机毕业设计源码+系统+lw文档+mysql数据库+调试部署

    基于java安防管理平台计算机毕业设计源码+系统+lw文档+mysql数据库+调试部署 基于java安防管理平台计算机毕业设计源码+系统+lw文档+mysql数据库+调试部署 本源码技术栈: 项目架构 ...

  2. 基于JAVA智能外包管理平台计算机毕业设计源码+系统+lw文档+部署

    基于JAVA智能外包管理平台计算机毕业设计源码+系统+lw文档+部署 基于JAVA智能外包管理平台计算机毕业设计源码+系统+lw文档+部署 本源码技术栈: 项目架构:B/S架构 开发语言:Java语言 ...

  3. 基于JavaWeb的健康管理平台-源码+论文

    今天介绍的项目是基于JavaWeb的健康管理平台, 主要内容如下 1.1 设计背景 紧张的工作节奏.教学和科研的压力.个人不良的工作生活习惯.以及伴随工作压力而来的家庭关系.人际关系紧张等因素使得高校 ...

  4. 基于JAVA高校实习管理平台系统计算机毕业设计源码+数据库+lw文档+系统+部署

    基于JAVA高校实习管理平台系统计算机毕业设计源码+数据库+lw文档+系统+部署 基于JAVA高校实习管理平台系统计算机毕业设计源码+数据库+lw文档+系统+部署 本源码技术栈: 项目架构:B/S架构 ...

  5. (附源码)springboot基于SpringBoot的教学管理平台的设计与实现281454

    目  录 摘要 1 绪论 1.1研究背景 1.2研究现状 1.3系统开发技术的特色 1.4论文结构与章节安排 2教学管理平台系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1数据增加流程 ...

  6. 基于JAVA中小学教务管理平台计算机毕业设计源码+系统+数据库+lw文档+部署

    基于JAVA中小学教务管理平台计算机毕业设计源码+系统+数据库+lw文档+部署 基于JAVA中小学教务管理平台计算机毕业设计源码+系统+数据库+lw文档+部署 本源码技术栈: 项目架构:B/S架构 开 ...

  7. 基于JAVA学生住宿管理平台计算机毕业设计源码+系统+数据库+lw文档+部署

    基于JAVA学生住宿管理平台计算机毕业设计源码+系统+数据库+lw文档+部署 基于JAVA学生住宿管理平台计算机毕业设计源码+系统+数据库+lw文档+部署 本源码技术栈: 项目架构:B/S架构 开发语 ...

  8. SSM毕设项目基于java的服装店管理平台h254j(java+VUE+Mybatis+Maven+Mysql)

    SSM毕设项目基于java的服装店管理平台h254j(java+VUE+Mybatis+Maven+Mysql) 项目运行 环境配置: Jdk1.8 + Tomcat8.5 + Mysql + HBu ...

  9. 基于JAVA牙科诊所信息化管理平台计算机毕业设计源码+系统+lw文档+部署

    基于JAVA牙科诊所信息化管理平台计算机毕业设计源码+系统+lw文档+部署 基于JAVA牙科诊所信息化管理平台计算机毕业设计源码+系统+lw文档+部署 本源码技术栈: 项目架构:B/S架构 开发语言: ...

最新文章

  1. go get 无法下载问题解决方案及下载 aliyun-oss-go-sdk incompatible.info
  2. 关于CSS样式浏览器兼容问题的一些注意事项
  3. (深入理解)matplotlib绘图原理(figure,axes,axis,canvas的区别)
  4. 计算矩阵连乘积(动态规划)
  5. buuctf 基础破解
  6. (原创)c#学习笔记08--面向对象编程简介02--OOP技术05--运算符重载
  7. 基于.NET Framework 4.0的解决方案部署
  8. 五、python模块以及包
  9. 怎么更改Windows11鼠标指针大小和样式
  10. 03-23 卡顿分析
  11. git 常见问题的解决方案
  12. ccs加载out文件,TI CCS3.3 out文件转bin文件说明
  13. Android高德混淆问题
  14. 如何看待社会的阴暗面
  15. 条形码识别(3)——译码
  16. 想象力无限,人工智能时代你对AGV有什么期许
  17. 计算机视觉领域的发展趋势
  18. CUDA 深入浅出谈[转]
  19. web应用商城部署(gpmall)
  20. 新手值得一看!MacOS中Dock栏的设置和使用技巧

热门文章

  1. 夫妻两一个两年内3张卡9次逾期,一人4次,还能办理房贷吗?
  2. 北京某打工子弟学校之二
  3. 深入理解const char*p,char const*p,char *const p,const char **p,char const**p,char *const*p,char**const
  4. Hive注册表那点事(5.0 VS 6.0)
  5. 计算机技能节活动作文,技能节感想作文
  6. java的基础类库称为_JAVA基本类库介绍
  7. ZoomBlur 聚焦模糊效果Shader(URP)
  8. 【theano-windows】学习笔记六——theano中的循环函数scan
  9. python基础之常用的高阶函数
  10. maven之阿里云Maven镜像的使用