1消息传输协议使用了Google Protobuf,效率更高
2客户端示例基于Android Studio 3删除了flash sdk,将不再维护flash sdk 4 netty版本升级最新版,以及文档修改
@ -1,42 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<actionScriptProperties analytics="false" mainApplicationPath="CIMBridge.as" projectUUID="03408a4e-ab34-4064-b20b-a105b4fb81be" version="11">
|
||||
<compiler additionalCompilerArguments="-locale en_US" advancedTelemetry="false" autoRSLOrdering="true" copyDependentFiles="true" fteInMXComponents="false" generateAccessible="false" htmlExpressInstall="true" htmlGenerate="true" htmlHistoryManagement="true" htmlPlayerVersionCheck="true" includeNetmonSwc="false" outputFolderPath="bin-debug" removeUnusedRSL="true" sourceFolderPath="src" strict="true" targetPlayerVersion="0.0.0" useApolloConfig="false" useDebugRSLSwfs="true" useFlashSDK="true" verifyDigests="true" warn="true">
|
||||
<compilerSourcePath/>
|
||||
<libraryPath defaultLinkType="0">
|
||||
<libraryPathEntry kind="4" path="">
|
||||
<excludedEntries>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_charts.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="1" linkType="1" path="${PROJECT_FRAMEWORKS}/locale/{locale}"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/advancedgrids.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/qtp.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_air.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/charts.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/framework.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/mx/mx.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/netmon.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/spark.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/sparkskins.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/rpc.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/datavisualization.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/qtp_air.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/videoPlayer.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/spark_dmv.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_dmv.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/flash-integration.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_flashflexkit.swc" useDefaultLinkType="false"/>
|
||||
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_agent.swc" useDefaultLinkType="false"/>
|
||||
</excludedEntries>
|
||||
</libraryPathEntry>
|
||||
<libraryPathEntry kind="3" linkType="1" path="libs/as3corelib.swc" useDefaultLinkType="false"/>
|
||||
</libraryPath>
|
||||
<sourceAttachmentPath/>
|
||||
</compiler>
|
||||
<applications>
|
||||
<application path="CIMBridge.as"/>
|
||||
</applications>
|
||||
<modules/>
|
||||
<workers/>
|
||||
<buildCSSFiles/>
|
||||
<flashCatalyst validateFlashCatalystCompatibility="false"/>
|
||||
</actionScriptProperties>
|
@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>CIMFlashBridge</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>com.adobe.flexbuilder.project.flexbuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>com.adobe.flexbuilder.project.actionscriptnature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
@ -1,3 +0,0 @@
|
||||
#Mon Sep 22 14:10:44 CST 2014
|
||||
eclipse.preferences.version=1
|
||||
encoding/<project>=utf-8
|
@ -1,108 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<!-- saved from url=(0014)about:internet -->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
|
||||
<!--
|
||||
Smart developers always View Source.
|
||||
|
||||
This application was built using Adobe Flex, an open source framework
|
||||
for building rich Internet applications that get delivered via the
|
||||
Flash Player or to desktops via Adobe AIR.
|
||||
|
||||
Learn more about Flex at http://flex.org
|
||||
// -->
|
||||
<head>
|
||||
<title></title>
|
||||
<meta name="google" value="notranslate" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<!-- Include CSS to eliminate any default margins/padding and set the height of the html element and
|
||||
the body element to 100%, because Firefox, or any Gecko based browser, interprets percentage as
|
||||
the percentage of the height of its parent container, which has to be set explicitly. Fix for
|
||||
Firefox 3.6 focus border issues. Initially, don't display flashContent div so it won't show
|
||||
if JavaScript disabled.
|
||||
-->
|
||||
<style type="text/css" media="screen">
|
||||
html, body { height:100%; }
|
||||
body { margin:0; padding:0; overflow:auto; text-align:center;
|
||||
background-color: #ffffff; }
|
||||
object:focus { outline:none; }
|
||||
#flashContent { display:none; }
|
||||
</style>
|
||||
|
||||
<!-- Enable Browser History by replacing useBrowserHistory tokens with two hyphens -->
|
||||
<!-- BEGIN Browser History required section -->
|
||||
<link rel="stylesheet" type="text/css" href="history/history.css" />
|
||||
<script type="text/javascript" src="history/history.js"></script>
|
||||
<!-- END Browser History required section -->
|
||||
|
||||
<script type="text/javascript" src="swfobject.js"></script>
|
||||
<script type="text/javascript">
|
||||
// For version detection, set to min. required Flash Player version, or 0 (or 0.0.0), for no version detection.
|
||||
var swfVersionStr = "11.4.0";
|
||||
// To use express install, set to playerProductInstall.swf, otherwise the empty string.
|
||||
var xiSwfUrlStr = "playerProductInstall.swf";
|
||||
var flashvars = {};
|
||||
var params = {};
|
||||
params.quality = "high";
|
||||
params.bgcolor = "#ffffff";
|
||||
params.allowscriptaccess = "sameDomain";
|
||||
params.allowfullscreen = "true";
|
||||
var attributes = {};
|
||||
attributes.id = "CIMBridge";
|
||||
attributes.name = "CIMBridge";
|
||||
attributes.align = "middle";
|
||||
swfobject.embedSWF(
|
||||
"CIMBridge.swf", "flashContent",
|
||||
"100%", "100%",
|
||||
swfVersionStr, xiSwfUrlStr,
|
||||
flashvars, params, attributes);
|
||||
// JavaScript enabled so display the flashContent div in case it is not replaced with a swf object.
|
||||
swfobject.createCSS("#flashContent", "display:block;text-align:left;");
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- SWFObject's dynamic embed method replaces this alternative HTML content with Flash content when enough
|
||||
JavaScript and Flash plug-in support is available. The div is initially hidden so that it doesn't show
|
||||
when JavaScript is disabled.
|
||||
-->
|
||||
<div id="flashContent">
|
||||
<p>
|
||||
To view this page ensure that Adobe Flash Player version
|
||||
11.4.0 or greater is installed.
|
||||
</p>
|
||||
<script type="text/javascript">
|
||||
var pageHost = ((document.location.protocol == "https:") ? "https://" : "http://");
|
||||
document.write("<a href='http://www.adobe.com/go/getflashplayer'><img src='"
|
||||
+ pageHost + "www.adobe.com/images/shared/download_buttons/get_flash_player.gif' alt='Get Adobe Flash player' /></a>" );
|
||||
</script>
|
||||
</div>
|
||||
|
||||
<noscript>
|
||||
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="100%" height="100%" id="CIMBridge">
|
||||
<param name="movie" value="CIMBridge.swf" />
|
||||
<param name="quality" value="high" />
|
||||
<param name="bgcolor" value="#ffffff" />
|
||||
<param name="allowScriptAccess" value="sameDomain" />
|
||||
<param name="allowFullScreen" value="true" />
|
||||
<!--[if !IE]>-->
|
||||
<object type="application/x-shockwave-flash" data="CIMBridge.swf" width="100%" height="100%">
|
||||
<param name="quality" value="high" />
|
||||
<param name="bgcolor" value="#ffffff" />
|
||||
<param name="allowScriptAccess" value="sameDomain" />
|
||||
<param name="allowFullScreen" value="true" />
|
||||
<!--<![endif]-->
|
||||
<!--[if gte IE 6]>-->
|
||||
<p>
|
||||
Either scripts and active content are not permitted to run or Adobe Flash Player version
|
||||
11.4.0 or greater is not installed.
|
||||
</p>
|
||||
<!--<![endif]-->
|
||||
<a href="http://www.adobe.com/go/getflashplayer">
|
||||
<img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash Player" />
|
||||
</a>
|
||||
<!--[if !IE]>-->
|
||||
</object>
|
||||
<!--<![endif]-->
|
||||
</object>
|
||||
</noscript>
|
||||
</body>
|
||||
</html>
|
@ -1,108 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<!-- saved from url=(0014)about:internet -->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
|
||||
<!--
|
||||
Smart developers always View Source.
|
||||
|
||||
This application was built using Adobe Flex, an open source framework
|
||||
for building rich Internet applications that get delivered via the
|
||||
Flash Player or to desktops via Adobe AIR.
|
||||
|
||||
Learn more about Flex at http://flex.org
|
||||
// -->
|
||||
<head>
|
||||
<title></title>
|
||||
<meta name="google" value="notranslate" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<!-- Include CSS to eliminate any default margins/padding and set the height of the html element and
|
||||
the body element to 100%, because Firefox, or any Gecko based browser, interprets percentage as
|
||||
the percentage of the height of its parent container, which has to be set explicitly. Fix for
|
||||
Firefox 3.6 focus border issues. Initially, don't display flashContent div so it won't show
|
||||
if JavaScript disabled.
|
||||
-->
|
||||
<style type="text/css" media="screen">
|
||||
html, body { height:100%; }
|
||||
body { margin:0; padding:0; overflow:auto; text-align:center;
|
||||
background-color: #ffffff; }
|
||||
object:focus { outline:none; }
|
||||
#flashContent { display:none; }
|
||||
</style>
|
||||
|
||||
<!-- Enable Browser History by replacing useBrowserHistory tokens with two hyphens -->
|
||||
<!-- BEGIN Browser History required section -->
|
||||
<link rel="stylesheet" type="text/css" href="history/history.css" />
|
||||
<script type="text/javascript" src="history/history.js"></script>
|
||||
<!-- END Browser History required section -->
|
||||
|
||||
<script type="text/javascript" src="swfobject.js"></script>
|
||||
<script type="text/javascript">
|
||||
// For version detection, set to min. required Flash Player version, or 0 (or 0.0.0), for no version detection.
|
||||
var swfVersionStr = "11.4.0";
|
||||
// To use express install, set to playerProductInstall.swf, otherwise the empty string.
|
||||
var xiSwfUrlStr = "playerProductInstall.swf";
|
||||
var flashvars = {};
|
||||
var params = {};
|
||||
params.quality = "high";
|
||||
params.bgcolor = "#ffffff";
|
||||
params.allowscriptaccess = "sameDomain";
|
||||
params.allowfullscreen = "true";
|
||||
var attributes = {};
|
||||
attributes.id = "cim";
|
||||
attributes.name = "cim";
|
||||
attributes.align = "middle";
|
||||
swfobject.embedSWF(
|
||||
"cim.swf", "flashContent",
|
||||
"100%", "100%",
|
||||
swfVersionStr, xiSwfUrlStr,
|
||||
flashvars, params, attributes);
|
||||
// JavaScript enabled so display the flashContent div in case it is not replaced with a swf object.
|
||||
swfobject.createCSS("#flashContent", "display:block;text-align:left;");
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- SWFObject's dynamic embed method replaces this alternative HTML content with Flash content when enough
|
||||
JavaScript and Flash plug-in support is available. The div is initially hidden so that it doesn't show
|
||||
when JavaScript is disabled.
|
||||
-->
|
||||
<div id="flashContent">
|
||||
<p>
|
||||
To view this page ensure that Adobe Flash Player version
|
||||
11.4.0 or greater is installed.
|
||||
</p>
|
||||
<script type="text/javascript">
|
||||
var pageHost = ((document.location.protocol == "https:") ? "https://" : "http://");
|
||||
document.write("<a href='http://www.adobe.com/go/getflashplayer'><img src='"
|
||||
+ pageHost + "www.adobe.com/images/shared/download_buttons/get_flash_player.gif' alt='Get Adobe Flash player' /></a>" );
|
||||
</script>
|
||||
</div>
|
||||
|
||||
<noscript>
|
||||
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="100%" height="100%" id="cim">
|
||||
<param name="movie" value="cim.swf" />
|
||||
<param name="quality" value="high" />
|
||||
<param name="bgcolor" value="#ffffff" />
|
||||
<param name="allowScriptAccess" value="sameDomain" />
|
||||
<param name="allowFullScreen" value="true" />
|
||||
<!--[if !IE]>-->
|
||||
<object type="application/x-shockwave-flash" data="cim.swf" width="100%" height="100%">
|
||||
<param name="quality" value="high" />
|
||||
<param name="bgcolor" value="#ffffff" />
|
||||
<param name="allowScriptAccess" value="sameDomain" />
|
||||
<param name="allowFullScreen" value="true" />
|
||||
<!--<![endif]-->
|
||||
<!--[if gte IE 6]>-->
|
||||
<p>
|
||||
Either scripts and active content are not permitted to run or Adobe Flash Player version
|
||||
11.4.0 or greater is not installed.
|
||||
</p>
|
||||
<!--<![endif]-->
|
||||
<a href="http://www.adobe.com/go/getflashplayer">
|
||||
<img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash Player" />
|
||||
</a>
|
||||
<!--[if !IE]>-->
|
||||
</object>
|
||||
<!--<![endif]-->
|
||||
</object>
|
||||
</noscript>
|
||||
</body>
|
||||
</html>
|
@ -1,6 +0,0 @@
|
||||
/* This CSS stylesheet defines styles used by required elements in a flex application page that supports browser history */
|
||||
|
||||
#ie_historyFrame { width: 0px; height: 0px; display:none }
|
||||
#firefox_anchorDiv { width: 0px; height: 0px; display:none }
|
||||
#safari_formDiv { width: 0px; height: 0px; display:none }
|
||||
#safari_rememberDiv { width: 0px; height: 0px; display:none }
|
@ -1,678 +0,0 @@
|
||||
BrowserHistoryUtils = {
|
||||
addEvent: function(elm, evType, fn, useCapture) {
|
||||
useCapture = useCapture || false;
|
||||
if (elm.addEventListener) {
|
||||
elm.addEventListener(evType, fn, useCapture);
|
||||
return true;
|
||||
}
|
||||
else if (elm.attachEvent) {
|
||||
var r = elm.attachEvent('on' + evType, fn);
|
||||
return r;
|
||||
}
|
||||
else {
|
||||
elm['on' + evType] = fn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BrowserHistory = (function() {
|
||||
// type of browser
|
||||
var browser = {
|
||||
ie: false,
|
||||
ie8: false,
|
||||
firefox: false,
|
||||
safari: false,
|
||||
opera: false,
|
||||
version: -1
|
||||
};
|
||||
|
||||
// Default app state URL to use when no fragment ID present
|
||||
var defaultHash = '';
|
||||
|
||||
// Last-known app state URL
|
||||
var currentHref = document.location.href;
|
||||
|
||||
// Initial URL (used only by IE)
|
||||
var initialHref = document.location.href;
|
||||
|
||||
// Initial URL (used only by IE)
|
||||
var initialHash = document.location.hash;
|
||||
|
||||
// History frame source URL prefix (used only by IE)
|
||||
var historyFrameSourcePrefix = 'history/historyFrame.html?';
|
||||
|
||||
// History maintenance (used only by Safari)
|
||||
var currentHistoryLength = -1;
|
||||
|
||||
// Flag to denote the existence of onhashchange
|
||||
var browserHasHashChange = false;
|
||||
|
||||
var historyHash = [];
|
||||
|
||||
var initialState = createState(initialHref, initialHref + '#' + initialHash, initialHash);
|
||||
|
||||
var backStack = [];
|
||||
var forwardStack = [];
|
||||
|
||||
var currentObjectId = null;
|
||||
|
||||
//UserAgent detection
|
||||
var useragent = navigator.userAgent.toLowerCase();
|
||||
|
||||
if (useragent.indexOf("opera") != -1) {
|
||||
browser.opera = true;
|
||||
} else if (useragent.indexOf("msie") != -1) {
|
||||
browser.ie = true;
|
||||
browser.version = parseFloat(useragent.substring(useragent.indexOf('msie') + 4));
|
||||
if (browser.version == 8)
|
||||
{
|
||||
browser.ie = false;
|
||||
browser.ie8 = true;
|
||||
}
|
||||
} else if (useragent.indexOf("safari") != -1) {
|
||||
browser.safari = true;
|
||||
browser.version = parseFloat(useragent.substring(useragent.indexOf('safari') + 7));
|
||||
} else if (useragent.indexOf("gecko") != -1) {
|
||||
browser.firefox = true;
|
||||
}
|
||||
|
||||
if (browser.ie == true && browser.version == 7) {
|
||||
window["_ie_firstload"] = false;
|
||||
}
|
||||
|
||||
function hashChangeHandler()
|
||||
{
|
||||
currentHref = document.location.href;
|
||||
var flexAppUrl = getHash();
|
||||
//ADR: to fix multiple
|
||||
if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) {
|
||||
var pl = getPlayers();
|
||||
for (var i = 0; i < pl.length; i++) {
|
||||
pl[i].browserURLChange(flexAppUrl);
|
||||
}
|
||||
} else {
|
||||
getPlayer().browserURLChange(flexAppUrl);
|
||||
}
|
||||
}
|
||||
|
||||
// Accessor functions for obtaining specific elements of the page.
|
||||
function getHistoryFrame()
|
||||
{
|
||||
return document.getElementById('ie_historyFrame');
|
||||
}
|
||||
|
||||
function getFormElement()
|
||||
{
|
||||
return document.getElementById('safari_formDiv');
|
||||
}
|
||||
|
||||
function getRememberElement()
|
||||
{
|
||||
return document.getElementById("safari_remember_field");
|
||||
}
|
||||
|
||||
// Get the Flash player object for performing ExternalInterface callbacks.
|
||||
// Updated for changes to SWFObject2.
|
||||
function getPlayer(id) {
|
||||
var i;
|
||||
|
||||
if (id && document.getElementById(id)) {
|
||||
var r = document.getElementById(id);
|
||||
if (typeof r.SetVariable != "undefined") {
|
||||
return r;
|
||||
}
|
||||
else {
|
||||
var o = r.getElementsByTagName("object");
|
||||
var e = r.getElementsByTagName("embed");
|
||||
for (i = 0; i < o.length; i++) {
|
||||
if (typeof o[i].browserURLChange != "undefined")
|
||||
return o[i];
|
||||
}
|
||||
for (i = 0; i < e.length; i++) {
|
||||
if (typeof e[i].browserURLChange != "undefined")
|
||||
return e[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
var o = document.getElementsByTagName("object");
|
||||
var e = document.getElementsByTagName("embed");
|
||||
for (i = 0; i < e.length; i++) {
|
||||
if (typeof e[i].browserURLChange != "undefined")
|
||||
{
|
||||
return e[i];
|
||||
}
|
||||
}
|
||||
for (i = 0; i < o.length; i++) {
|
||||
if (typeof o[i].browserURLChange != "undefined")
|
||||
{
|
||||
return o[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getPlayers() {
|
||||
var i;
|
||||
var players = [];
|
||||
if (players.length == 0) {
|
||||
var tmp = document.getElementsByTagName('object');
|
||||
for (i = 0; i < tmp.length; i++)
|
||||
{
|
||||
if (typeof tmp[i].browserURLChange != "undefined")
|
||||
players.push(tmp[i]);
|
||||
}
|
||||
}
|
||||
if (players.length == 0 || players[0].object == null) {
|
||||
var tmp = document.getElementsByTagName('embed');
|
||||
for (i = 0; i < tmp.length; i++)
|
||||
{
|
||||
if (typeof tmp[i].browserURLChange != "undefined")
|
||||
players.push(tmp[i]);
|
||||
}
|
||||
}
|
||||
return players;
|
||||
}
|
||||
|
||||
function getIframeHash() {
|
||||
var doc = getHistoryFrame().contentWindow.document;
|
||||
var hash = String(doc.location.search);
|
||||
if (hash.length == 1 && hash.charAt(0) == "?") {
|
||||
hash = "";
|
||||
}
|
||||
else if (hash.length >= 2 && hash.charAt(0) == "?") {
|
||||
hash = hash.substring(1);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
/* Get the current location hash excluding the '#' symbol. */
|
||||
function getHash() {
|
||||
// It would be nice if we could use document.location.hash here,
|
||||
// but it's faulty sometimes.
|
||||
var idx = document.location.href.indexOf('#');
|
||||
return (idx >= 0) ? document.location.href.substr(idx+1) : '';
|
||||
}
|
||||
|
||||
/* Get the current location hash excluding the '#' symbol. */
|
||||
function setHash(hash) {
|
||||
// It would be nice if we could use document.location.hash here,
|
||||
// but it's faulty sometimes.
|
||||
if (hash == '') hash = '#'
|
||||
document.location.hash = hash;
|
||||
}
|
||||
|
||||
function createState(baseUrl, newUrl, flexAppUrl) {
|
||||
return { 'baseUrl': baseUrl, 'newUrl': newUrl, 'flexAppUrl': flexAppUrl, 'title': null };
|
||||
}
|
||||
|
||||
/* Add a history entry to the browser.
|
||||
* baseUrl: the portion of the location prior to the '#'
|
||||
* newUrl: the entire new URL, including '#' and following fragment
|
||||
* flexAppUrl: the portion of the location following the '#' only
|
||||
*/
|
||||
function addHistoryEntry(baseUrl, newUrl, flexAppUrl) {
|
||||
|
||||
//delete all the history entries
|
||||
forwardStack = [];
|
||||
|
||||
if (browser.ie) {
|
||||
//Check to see if we are being asked to do a navigate for the first
|
||||
//history entry, and if so ignore, because it's coming from the creation
|
||||
//of the history iframe
|
||||
if (flexAppUrl == defaultHash && document.location.href == initialHref && window['_ie_firstload']) {
|
||||
currentHref = initialHref;
|
||||
return;
|
||||
}
|
||||
if ((!flexAppUrl || flexAppUrl == defaultHash) && window['_ie_firstload']) {
|
||||
newUrl = baseUrl + '#' + defaultHash;
|
||||
flexAppUrl = defaultHash;
|
||||
} else {
|
||||
// for IE, tell the history frame to go somewhere without a '#'
|
||||
// in order to get this entry into the browser history.
|
||||
getHistoryFrame().src = historyFrameSourcePrefix + flexAppUrl;
|
||||
}
|
||||
setHash(flexAppUrl);
|
||||
} else {
|
||||
|
||||
//ADR
|
||||
if (backStack.length == 0 && initialState.flexAppUrl == flexAppUrl) {
|
||||
initialState = createState(baseUrl, newUrl, flexAppUrl);
|
||||
} else if(backStack.length > 0 && backStack[backStack.length - 1].flexAppUrl == flexAppUrl) {
|
||||
backStack[backStack.length - 1] = createState(baseUrl, newUrl, flexAppUrl);
|
||||
}
|
||||
|
||||
if (browser.safari && !browserHasHashChange) {
|
||||
// for Safari, submit a form whose action points to the desired URL
|
||||
if (browser.version <= 419.3) {
|
||||
var file = window.location.pathname.toString();
|
||||
file = file.substring(file.lastIndexOf("/")+1);
|
||||
getFormElement().innerHTML = '<form name="historyForm" action="'+file+'#' + flexAppUrl + '" method="GET"></form>';
|
||||
//get the current elements and add them to the form
|
||||
var qs = window.location.search.substring(1);
|
||||
var qs_arr = qs.split("&");
|
||||
for (var i = 0; i < qs_arr.length; i++) {
|
||||
var tmp = qs_arr[i].split("=");
|
||||
var elem = document.createElement("input");
|
||||
elem.type = "hidden";
|
||||
elem.name = tmp[0];
|
||||
elem.value = tmp[1];
|
||||
document.forms.historyForm.appendChild(elem);
|
||||
}
|
||||
document.forms.historyForm.submit();
|
||||
} else {
|
||||
top.location.hash = flexAppUrl;
|
||||
}
|
||||
// We also have to maintain the history by hand for Safari
|
||||
historyHash[history.length] = flexAppUrl;
|
||||
_storeStates();
|
||||
} else {
|
||||
// Otherwise, just tell the browser to go there
|
||||
setHash(flexAppUrl);
|
||||
}
|
||||
}
|
||||
backStack.push(createState(baseUrl, newUrl, flexAppUrl));
|
||||
}
|
||||
|
||||
function _storeStates() {
|
||||
if (browser.safari) {
|
||||
getRememberElement().value = historyHash.join(",");
|
||||
}
|
||||
}
|
||||
|
||||
function handleBackButton() {
|
||||
//The "current" page is always at the top of the history stack.
|
||||
var current = backStack.pop();
|
||||
if (!current) { return; }
|
||||
var last = backStack[backStack.length - 1];
|
||||
if (!last && backStack.length == 0){
|
||||
last = initialState;
|
||||
}
|
||||
forwardStack.push(current);
|
||||
}
|
||||
|
||||
function handleForwardButton() {
|
||||
//summary: private method. Do not call this directly.
|
||||
|
||||
var last = forwardStack.pop();
|
||||
if (!last) { return; }
|
||||
backStack.push(last);
|
||||
}
|
||||
|
||||
function handleArbitraryUrl() {
|
||||
//delete all the history entries
|
||||
forwardStack = [];
|
||||
}
|
||||
|
||||
/* Called periodically to poll to see if we need to detect navigation that has occurred */
|
||||
function checkForUrlChange() {
|
||||
|
||||
if (browser.ie) {
|
||||
if (currentHref != document.location.href && currentHref + '#' != document.location.href) {
|
||||
//This occurs when the user has navigated to a specific URL
|
||||
//within the app, and didn't use browser back/forward
|
||||
//IE seems to have a bug where it stops updating the URL it
|
||||
//shows the end-user at this point, but programatically it
|
||||
//appears to be correct. Do a full app reload to get around
|
||||
//this issue.
|
||||
if (browser.version < 7) {
|
||||
currentHref = document.location.href;
|
||||
document.location.reload();
|
||||
} else {
|
||||
if (getHash() != getIframeHash()) {
|
||||
// this.iframe.src = this.blankURL + hash;
|
||||
var sourceToSet = historyFrameSourcePrefix + getHash();
|
||||
getHistoryFrame().src = sourceToSet;
|
||||
currentHref = document.location.href;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (browser.safari && !browserHasHashChange) {
|
||||
// For Safari, we have to check to see if history.length changed.
|
||||
if (currentHistoryLength >= 0 && history.length != currentHistoryLength) {
|
||||
//alert("did change: " + history.length + ", " + historyHash.length + "|" + historyHash[history.length] + "|>" + historyHash.join("|"));
|
||||
var flexAppUrl = getHash();
|
||||
if (browser.version < 528.16 /* Anything earlier than Safari 4.0 */)
|
||||
{
|
||||
// If it did change and we're running Safari 3.x or earlier,
|
||||
// then we have to look the old state up in our hand-maintained
|
||||
// array since document.location.hash won't have changed,
|
||||
// then call back into BrowserManager.
|
||||
currentHistoryLength = history.length;
|
||||
flexAppUrl = historyHash[currentHistoryLength];
|
||||
}
|
||||
|
||||
//ADR: to fix multiple
|
||||
if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) {
|
||||
var pl = getPlayers();
|
||||
for (var i = 0; i < pl.length; i++) {
|
||||
pl[i].browserURLChange(flexAppUrl);
|
||||
}
|
||||
} else {
|
||||
getPlayer().browserURLChange(flexAppUrl);
|
||||
}
|
||||
_storeStates();
|
||||
}
|
||||
}
|
||||
if (browser.firefox && !browserHasHashChange) {
|
||||
if (currentHref != document.location.href) {
|
||||
var bsl = backStack.length;
|
||||
|
||||
var urlActions = {
|
||||
back: false,
|
||||
forward: false,
|
||||
set: false
|
||||
}
|
||||
|
||||
if ((window.location.hash == initialHash || window.location.href == initialHref) && (bsl == 1)) {
|
||||
urlActions.back = true;
|
||||
// FIXME: could this ever be a forward button?
|
||||
// we can't clear it because we still need to check for forwards. Ugg.
|
||||
// clearInterval(this.locationTimer);
|
||||
handleBackButton();
|
||||
}
|
||||
|
||||
// first check to see if we could have gone forward. We always halt on
|
||||
// a no-hash item.
|
||||
if (forwardStack.length > 0) {
|
||||
if (forwardStack[forwardStack.length-1].flexAppUrl == getHash()) {
|
||||
urlActions.forward = true;
|
||||
handleForwardButton();
|
||||
}
|
||||
}
|
||||
|
||||
// ok, that didn't work, try someplace back in the history stack
|
||||
if ((bsl >= 2) && (backStack[bsl - 2])) {
|
||||
if (backStack[bsl - 2].flexAppUrl == getHash()) {
|
||||
urlActions.back = true;
|
||||
handleBackButton();
|
||||
}
|
||||
}
|
||||
|
||||
if (!urlActions.back && !urlActions.forward) {
|
||||
var foundInStacks = {
|
||||
back: -1,
|
||||
forward: -1
|
||||
}
|
||||
|
||||
for (var i = 0; i < backStack.length; i++) {
|
||||
if (backStack[i].flexAppUrl == getHash() && i != (bsl - 2)) {
|
||||
arbitraryUrl = true;
|
||||
foundInStacks.back = i;
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < forwardStack.length; i++) {
|
||||
if (forwardStack[i].flexAppUrl == getHash() && i != (bsl - 2)) {
|
||||
arbitraryUrl = true;
|
||||
foundInStacks.forward = i;
|
||||
}
|
||||
}
|
||||
handleArbitraryUrl();
|
||||
}
|
||||
|
||||
// Firefox changed; do a callback into BrowserManager to tell it.
|
||||
currentHref = document.location.href;
|
||||
var flexAppUrl = getHash();
|
||||
//ADR: to fix multiple
|
||||
if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) {
|
||||
var pl = getPlayers();
|
||||
for (var i = 0; i < pl.length; i++) {
|
||||
pl[i].browserURLChange(flexAppUrl);
|
||||
}
|
||||
} else {
|
||||
getPlayer().browserURLChange(flexAppUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var _initialize = function () {
|
||||
|
||||
browserHasHashChange = ("onhashchange" in document.body);
|
||||
|
||||
if (browser.ie)
|
||||
{
|
||||
var scripts = document.getElementsByTagName('script');
|
||||
for (var i = 0, s; s = scripts[i]; i++) {
|
||||
if (s.src.indexOf("history.js") > -1) {
|
||||
var iframe_location = (new String(s.src)).replace("history.js", "historyFrame.html");
|
||||
}
|
||||
}
|
||||
historyFrameSourcePrefix = iframe_location + "?";
|
||||
var src = historyFrameSourcePrefix;
|
||||
|
||||
var iframe = document.createElement("iframe");
|
||||
iframe.id = 'ie_historyFrame';
|
||||
iframe.name = 'ie_historyFrame';
|
||||
iframe.src = 'javascript:false;';
|
||||
|
||||
try {
|
||||
document.body.appendChild(iframe);
|
||||
} catch(e) {
|
||||
setTimeout(function() {
|
||||
document.body.appendChild(iframe);
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (browser.safari && !browserHasHashChange)
|
||||
{
|
||||
var rememberDiv = document.createElement("div");
|
||||
rememberDiv.id = 'safari_rememberDiv';
|
||||
document.body.appendChild(rememberDiv);
|
||||
rememberDiv.innerHTML = '<input type="text" id="safari_remember_field" style="width: 500px;">';
|
||||
|
||||
var formDiv = document.createElement("div");
|
||||
formDiv.id = 'safari_formDiv';
|
||||
document.body.appendChild(formDiv);
|
||||
|
||||
var reloader_content = document.createElement('div');
|
||||
reloader_content.id = 'safarireloader';
|
||||
var scripts = document.getElementsByTagName('script');
|
||||
for (var i = 0, s; s = scripts[i]; i++) {
|
||||
if (s.src.indexOf("history.js") > -1) {
|
||||
html = (new String(s.src)).replace(".js", ".html");
|
||||
}
|
||||
}
|
||||
reloader_content.innerHTML = '<iframe id="safarireloader-iframe" src="about:blank" frameborder="no" scrolling="no"></iframe>';
|
||||
document.body.appendChild(reloader_content);
|
||||
reloader_content.style.position = 'absolute';
|
||||
reloader_content.style.left = reloader_content.style.top = '-9999px';
|
||||
iframe = reloader_content.getElementsByTagName('iframe')[0];
|
||||
|
||||
if (document.getElementById("safari_remember_field").value != "" ) {
|
||||
historyHash = document.getElementById("safari_remember_field").value.split(",");
|
||||
}
|
||||
}
|
||||
|
||||
if (browserHasHashChange)
|
||||
document.body.onhashchange = hashChangeHandler;
|
||||
}
|
||||
|
||||
return {
|
||||
historyHash: historyHash,
|
||||
backStack: function() { return backStack; },
|
||||
forwardStack: function() { return forwardStack },
|
||||
getPlayer: getPlayer,
|
||||
initialize: function(src) {
|
||||
_initialize(src);
|
||||
},
|
||||
setURL: function(url) {
|
||||
document.location.href = url;
|
||||
},
|
||||
getURL: function() {
|
||||
return document.location.href;
|
||||
},
|
||||
getTitle: function() {
|
||||
return document.title;
|
||||
},
|
||||
setTitle: function(title) {
|
||||
try {
|
||||
backStack[backStack.length - 1].title = title;
|
||||
} catch(e) { }
|
||||
//if on safari, set the title to be the empty string.
|
||||
if (browser.safari) {
|
||||
if (title == "") {
|
||||
try {
|
||||
var tmp = window.location.href.toString();
|
||||
title = tmp.substring((tmp.lastIndexOf("/")+1), tmp.lastIndexOf("#"));
|
||||
} catch(e) {
|
||||
title = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
document.title = title;
|
||||
},
|
||||
setDefaultURL: function(def)
|
||||
{
|
||||
defaultHash = def;
|
||||
def = getHash();
|
||||
//trailing ? is important else an extra frame gets added to the history
|
||||
//when navigating back to the first page. Alternatively could check
|
||||
//in history frame navigation to compare # and ?.
|
||||
if (browser.ie)
|
||||
{
|
||||
window['_ie_firstload'] = true;
|
||||
var sourceToSet = historyFrameSourcePrefix + def;
|
||||
var func = function() {
|
||||
getHistoryFrame().src = sourceToSet;
|
||||
window.location.replace("#" + def);
|
||||
setInterval(checkForUrlChange, 50);
|
||||
}
|
||||
try {
|
||||
func();
|
||||
} catch(e) {
|
||||
window.setTimeout(function() { func(); }, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (browser.safari)
|
||||
{
|
||||
currentHistoryLength = history.length;
|
||||
if (historyHash.length == 0) {
|
||||
historyHash[currentHistoryLength] = def;
|
||||
var newloc = "#" + def;
|
||||
window.location.replace(newloc);
|
||||
} else {
|
||||
//alert(historyHash[historyHash.length-1]);
|
||||
}
|
||||
setInterval(checkForUrlChange, 50);
|
||||
}
|
||||
|
||||
|
||||
if (browser.firefox || browser.opera)
|
||||
{
|
||||
var reg = new RegExp("#" + def + "$");
|
||||
if (window.location.toString().match(reg)) {
|
||||
} else {
|
||||
var newloc ="#" + def;
|
||||
window.location.replace(newloc);
|
||||
}
|
||||
setInterval(checkForUrlChange, 50);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
/* Set the current browser URL; called from inside BrowserManager to propagate
|
||||
* the application state out to the container.
|
||||
*/
|
||||
setBrowserURL: function(flexAppUrl, objectId) {
|
||||
if (browser.ie && typeof objectId != "undefined") {
|
||||
currentObjectId = objectId;
|
||||
}
|
||||
//fromIframe = fromIframe || false;
|
||||
//fromFlex = fromFlex || false;
|
||||
//alert("setBrowserURL: " + flexAppUrl);
|
||||
//flexAppUrl = (flexAppUrl == "") ? defaultHash : flexAppUrl ;
|
||||
|
||||
var pos = document.location.href.indexOf('#');
|
||||
var baseUrl = pos != -1 ? document.location.href.substr(0, pos) : document.location.href;
|
||||
var newUrl = baseUrl + '#' + flexAppUrl;
|
||||
|
||||
if (document.location.href != newUrl && document.location.href + '#' != newUrl) {
|
||||
currentHref = newUrl;
|
||||
addHistoryEntry(baseUrl, newUrl, flexAppUrl);
|
||||
currentHistoryLength = history.length;
|
||||
}
|
||||
},
|
||||
|
||||
browserURLChange: function(flexAppUrl) {
|
||||
var objectId = null;
|
||||
if (browser.ie && currentObjectId != null) {
|
||||
objectId = currentObjectId;
|
||||
}
|
||||
|
||||
if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) {
|
||||
var pl = getPlayers();
|
||||
for (var i = 0; i < pl.length; i++) {
|
||||
try {
|
||||
pl[i].browserURLChange(flexAppUrl);
|
||||
} catch(e) { }
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
getPlayer(objectId).browserURLChange(flexAppUrl);
|
||||
} catch(e) { }
|
||||
}
|
||||
|
||||
currentObjectId = null;
|
||||
},
|
||||
getUserAgent: function() {
|
||||
return navigator.userAgent;
|
||||
},
|
||||
getPlatform: function() {
|
||||
return navigator.platform;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
// Initialization
|
||||
|
||||
// Automated unit testing and other diagnostics
|
||||
|
||||
function setURL(url)
|
||||
{
|
||||
document.location.href = url;
|
||||
}
|
||||
|
||||
function backButton()
|
||||
{
|
||||
history.back();
|
||||
}
|
||||
|
||||
function forwardButton()
|
||||
{
|
||||
history.forward();
|
||||
}
|
||||
|
||||
function goForwardOrBackInHistory(step)
|
||||
{
|
||||
history.go(step);
|
||||
}
|
||||
|
||||
//BrowserHistoryUtils.addEvent(window, "load", function() { BrowserHistory.initialize(); });
|
||||
(function(i) {
|
||||
var u =navigator.userAgent;var e=/*@cc_on!@*/false;
|
||||
var st = setTimeout;
|
||||
if(/webkit/i.test(u)){
|
||||
st(function(){
|
||||
var dr=document.readyState;
|
||||
if(dr=="loaded"||dr=="complete"){i()}
|
||||
else{st(arguments.callee,10);}},10);
|
||||
} else if((/mozilla/i.test(u)&&!/(compati)/.test(u)) || (/opera/i.test(u))){
|
||||
document.addEventListener("DOMContentLoaded",i,false);
|
||||
} else if(e){
|
||||
(function(){
|
||||
var t=document.createElement('doc:rdy');
|
||||
try{t.doScroll('left');
|
||||
i();t=null;
|
||||
}catch(e){st(arguments.callee,0);}})();
|
||||
} else{
|
||||
window.onload=i;
|
||||
}
|
||||
})( function() {BrowserHistory.initialize();} );
|
@ -1,29 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
|
||||
<META HTTP-EQUIV="Expires" CONTENT="-1">
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
function processUrl()
|
||||
{
|
||||
|
||||
var pos = url.indexOf("?");
|
||||
url = pos != -1 ? url.substr(pos + 1) : "";
|
||||
if (!parent._ie_firstload) {
|
||||
parent.BrowserHistory.setBrowserURL(url);
|
||||
try {
|
||||
parent.BrowserHistory.browserURLChange(url);
|
||||
} catch(e) { }
|
||||
} else {
|
||||
parent._ie_firstload = false;
|
||||
}
|
||||
}
|
||||
|
||||
var url = document.location.href;
|
||||
processUrl();
|
||||
document.write(encodeURIComponent(url));
|
||||
</script>
|
||||
Hidden frame for Browser History support.
|
||||
</body>
|
||||
</html>
|
@ -1,777 +0,0 @@
|
||||
/*! SWFObject v2.2 <http://code.google.com/p/swfobject/>
|
||||
is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
|
||||
*/
|
||||
|
||||
var swfobject = function() {
|
||||
|
||||
var UNDEF = "undefined",
|
||||
OBJECT = "object",
|
||||
SHOCKWAVE_FLASH = "Shockwave Flash",
|
||||
SHOCKWAVE_FLASH_AX = "ShockwaveFlash.ShockwaveFlash",
|
||||
FLASH_MIME_TYPE = "application/x-shockwave-flash",
|
||||
EXPRESS_INSTALL_ID = "SWFObjectExprInst",
|
||||
ON_READY_STATE_CHANGE = "onreadystatechange",
|
||||
|
||||
win = window,
|
||||
doc = document,
|
||||
nav = navigator,
|
||||
|
||||
plugin = false,
|
||||
domLoadFnArr = [main],
|
||||
regObjArr = [],
|
||||
objIdArr = [],
|
||||
listenersArr = [],
|
||||
storedAltContent,
|
||||
storedAltContentId,
|
||||
storedCallbackFn,
|
||||
storedCallbackObj,
|
||||
isDomLoaded = false,
|
||||
isExpressInstallActive = false,
|
||||
dynamicStylesheet,
|
||||
dynamicStylesheetMedia,
|
||||
autoHideShow = true,
|
||||
|
||||
/* Centralized function for browser feature detection
|
||||
- User agent string detection is only used when no good alternative is possible
|
||||
- Is executed directly for optimal performance
|
||||
*/
|
||||
ua = function() {
|
||||
var w3cdom = typeof doc.getElementById != UNDEF && typeof doc.getElementsByTagName != UNDEF && typeof doc.createElement != UNDEF,
|
||||
u = nav.userAgent.toLowerCase(),
|
||||
p = nav.platform.toLowerCase(),
|
||||
windows = p ? /win/.test(p) : /win/.test(u),
|
||||
mac = p ? /mac/.test(p) : /mac/.test(u),
|
||||
webkit = /webkit/.test(u) ? parseFloat(u.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, "$1")) : false, // returns either the webkit version or false if not webkit
|
||||
ie = !+"\v1", // feature detection based on Andrea Giammarchi's solution: http://webreflection.blogspot.com/2009/01/32-bytes-to-know-if-your-browser-is-ie.html
|
||||
playerVersion = [0,0,0],
|
||||
d = null;
|
||||
if (typeof nav.plugins != UNDEF && typeof nav.plugins[SHOCKWAVE_FLASH] == OBJECT) {
|
||||
d = nav.plugins[SHOCKWAVE_FLASH].description;
|
||||
if (d && !(typeof nav.mimeTypes != UNDEF && nav.mimeTypes[FLASH_MIME_TYPE] && !nav.mimeTypes[FLASH_MIME_TYPE].enabledPlugin)) { // navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin indicates whether plug-ins are enabled or disabled in Safari 3+
|
||||
plugin = true;
|
||||
ie = false; // cascaded feature detection for Internet Explorer
|
||||
d = d.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
|
||||
playerVersion[0] = parseInt(d.replace(/^(.*)\..*$/, "$1"), 10);
|
||||
playerVersion[1] = parseInt(d.replace(/^.*\.(.*)\s.*$/, "$1"), 10);
|
||||
playerVersion[2] = /[a-zA-Z]/.test(d) ? parseInt(d.replace(/^.*[a-zA-Z]+(.*)$/, "$1"), 10) : 0;
|
||||
}
|
||||
}
|
||||
else if (typeof win.ActiveXObject != UNDEF) {
|
||||
try {
|
||||
var a = new ActiveXObject(SHOCKWAVE_FLASH_AX);
|
||||
if (a) { // a will return null when ActiveX is disabled
|
||||
d = a.GetVariable("$version");
|
||||
if (d) {
|
||||
ie = true; // cascaded feature detection for Internet Explorer
|
||||
d = d.split(" ")[1].split(",");
|
||||
playerVersion = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(e) {}
|
||||
}
|
||||
return { w3:w3cdom, pv:playerVersion, wk:webkit, ie:ie, win:windows, mac:mac };
|
||||
}(),
|
||||
|
||||
/* Cross-browser onDomLoad
|
||||
- Will fire an event as soon as the DOM of a web page is loaded
|
||||
- Internet Explorer workaround based on Diego Perini's solution: http://javascript.nwbox.com/IEContentLoaded/
|
||||
- Regular onload serves as fallback
|
||||
*/
|
||||
onDomLoad = function() {
|
||||
if (!ua.w3) { return; }
|
||||
if ((typeof doc.readyState != UNDEF && doc.readyState == "complete") || (typeof doc.readyState == UNDEF && (doc.getElementsByTagName("body")[0] || doc.body))) { // function is fired after onload, e.g. when script is inserted dynamically
|
||||
callDomLoadFunctions();
|
||||
}
|
||||
if (!isDomLoaded) {
|
||||
if (typeof doc.addEventListener != UNDEF) {
|
||||
doc.addEventListener("DOMContentLoaded", callDomLoadFunctions, false);
|
||||
}
|
||||
if (ua.ie && ua.win) {
|
||||
doc.attachEvent(ON_READY_STATE_CHANGE, function() {
|
||||
if (doc.readyState == "complete") {
|
||||
doc.detachEvent(ON_READY_STATE_CHANGE, arguments.callee);
|
||||
callDomLoadFunctions();
|
||||
}
|
||||
});
|
||||
if (win == top) { // if not inside an iframe
|
||||
(function(){
|
||||
if (isDomLoaded) { return; }
|
||||
try {
|
||||
doc.documentElement.doScroll("left");
|
||||
}
|
||||
catch(e) {
|
||||
setTimeout(arguments.callee, 0);
|
||||
return;
|
||||
}
|
||||
callDomLoadFunctions();
|
||||
})();
|
||||
}
|
||||
}
|
||||
if (ua.wk) {
|
||||
(function(){
|
||||
if (isDomLoaded) { return; }
|
||||
if (!/loaded|complete/.test(doc.readyState)) {
|
||||
setTimeout(arguments.callee, 0);
|
||||
return;
|
||||
}
|
||||
callDomLoadFunctions();
|
||||
})();
|
||||
}
|
||||
addLoadEvent(callDomLoadFunctions);
|
||||
}
|
||||
}();
|
||||
|
||||
function callDomLoadFunctions() {
|
||||
if (isDomLoaded) { return; }
|
||||
try { // test if we can really add/remove elements to/from the DOM; we don't want to fire it too early
|
||||
var t = doc.getElementsByTagName("body")[0].appendChild(createElement("span"));
|
||||
t.parentNode.removeChild(t);
|
||||
}
|
||||
catch (e) { return; }
|
||||
isDomLoaded = true;
|
||||
var dl = domLoadFnArr.length;
|
||||
for (var i = 0; i < dl; i++) {
|
||||
domLoadFnArr[i]();
|
||||
}
|
||||
}
|
||||
|
||||
function addDomLoadEvent(fn) {
|
||||
if (isDomLoaded) {
|
||||
fn();
|
||||
}
|
||||
else {
|
||||
domLoadFnArr[domLoadFnArr.length] = fn; // Array.push() is only available in IE5.5+
|
||||
}
|
||||
}
|
||||
|
||||
/* Cross-browser onload
|
||||
- Based on James Edwards' solution: http://brothercake.com/site/resources/scripts/onload/
|
||||
- Will fire an event as soon as a web page including all of its assets are loaded
|
||||
*/
|
||||
function addLoadEvent(fn) {
|
||||
if (typeof win.addEventListener != UNDEF) {
|
||||
win.addEventListener("load", fn, false);
|
||||
}
|
||||
else if (typeof doc.addEventListener != UNDEF) {
|
||||
doc.addEventListener("load", fn, false);
|
||||
}
|
||||
else if (typeof win.attachEvent != UNDEF) {
|
||||
addListener(win, "onload", fn);
|
||||
}
|
||||
else if (typeof win.onload == "function") {
|
||||
var fnOld = win.onload;
|
||||
win.onload = function() {
|
||||
fnOld();
|
||||
fn();
|
||||
};
|
||||
}
|
||||
else {
|
||||
win.onload = fn;
|
||||
}
|
||||
}
|
||||
|
||||
/* Main function
|
||||
- Will preferably execute onDomLoad, otherwise onload (as a fallback)
|
||||
*/
|
||||
function main() {
|
||||
if (plugin) {
|
||||
testPlayerVersion();
|
||||
}
|
||||
else {
|
||||
matchVersions();
|
||||
}
|
||||
}
|
||||
|
||||
/* Detect the Flash Player version for non-Internet Explorer browsers
|
||||
- Detecting the plug-in version via the object element is more precise than using the plugins collection item's description:
|
||||
a. Both release and build numbers can be detected
|
||||
b. Avoid wrong descriptions by corrupt installers provided by Adobe
|
||||
c. Avoid wrong descriptions by multiple Flash Player entries in the plugin Array, caused by incorrect browser imports
|
||||
- Disadvantage of this method is that it depends on the availability of the DOM, while the plugins collection is immediately available
|
||||
*/
|
||||
function testPlayerVersion() {
|
||||
var b = doc.getElementsByTagName("body")[0];
|
||||
var o = createElement(OBJECT);
|
||||
o.setAttribute("type", FLASH_MIME_TYPE);
|
||||
var t = b.appendChild(o);
|
||||
if (t) {
|
||||
var counter = 0;
|
||||
(function(){
|
||||
if (typeof t.GetVariable != UNDEF) {
|
||||
var d = t.GetVariable("$version");
|
||||
if (d) {
|
||||
d = d.split(" ")[1].split(",");
|
||||
ua.pv = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
|
||||
}
|
||||
}
|
||||
else if (counter < 10) {
|
||||
counter++;
|
||||
setTimeout(arguments.callee, 10);
|
||||
return;
|
||||
}
|
||||
b.removeChild(o);
|
||||
t = null;
|
||||
matchVersions();
|
||||
})();
|
||||
}
|
||||
else {
|
||||
matchVersions();
|
||||
}
|
||||
}
|
||||
|
||||
/* Perform Flash Player and SWF version matching; static publishing only
|
||||
*/
|
||||
function matchVersions() {
|
||||
var rl = regObjArr.length;
|
||||
if (rl > 0) {
|
||||
for (var i = 0; i < rl; i++) { // for each registered object element
|
||||
var id = regObjArr[i].id;
|
||||
var cb = regObjArr[i].callbackFn;
|
||||
var cbObj = {success:false, id:id};
|
||||
if (ua.pv[0] > 0) {
|
||||
var obj = getElementById(id);
|
||||
if (obj) {
|
||||
if (hasPlayerVersion(regObjArr[i].swfVersion) && !(ua.wk && ua.wk < 312)) { // Flash Player version >= published SWF version: Houston, we have a match!
|
||||
setVisibility(id, true);
|
||||
if (cb) {
|
||||
cbObj.success = true;
|
||||
cbObj.ref = getObjectById(id);
|
||||
cb(cbObj);
|
||||
}
|
||||
}
|
||||
else if (regObjArr[i].expressInstall && canExpressInstall()) { // show the Adobe Express Install dialog if set by the web page author and if supported
|
||||
var att = {};
|
||||
att.data = regObjArr[i].expressInstall;
|
||||
att.width = obj.getAttribute("width") || "0";
|
||||
att.height = obj.getAttribute("height") || "0";
|
||||
if (obj.getAttribute("class")) { att.styleclass = obj.getAttribute("class"); }
|
||||
if (obj.getAttribute("align")) { att.align = obj.getAttribute("align"); }
|
||||
// parse HTML object param element's name-value pairs
|
||||
var par = {};
|
||||
var p = obj.getElementsByTagName("param");
|
||||
var pl = p.length;
|
||||
for (var j = 0; j < pl; j++) {
|
||||
if (p[j].getAttribute("name").toLowerCase() != "movie") {
|
||||
par[p[j].getAttribute("name")] = p[j].getAttribute("value");
|
||||
}
|
||||
}
|
||||
showExpressInstall(att, par, id, cb);
|
||||
}
|
||||
else { // Flash Player and SWF version mismatch or an older Webkit engine that ignores the HTML object element's nested param elements: display alternative content instead of SWF
|
||||
displayAltContent(obj);
|
||||
if (cb) { cb(cbObj); }
|
||||
}
|
||||
}
|
||||
}
|
||||
else { // if no Flash Player is installed or the fp version cannot be detected we let the HTML object element do its job (either show a SWF or alternative content)
|
||||
setVisibility(id, true);
|
||||
if (cb) {
|
||||
var o = getObjectById(id); // test whether there is an HTML object element or not
|
||||
if (o && typeof o.SetVariable != UNDEF) {
|
||||
cbObj.success = true;
|
||||
cbObj.ref = o;
|
||||
}
|
||||
cb(cbObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getObjectById(objectIdStr) {
|
||||
var r = null;
|
||||
var o = getElementById(objectIdStr);
|
||||
if (o && o.nodeName == "OBJECT") {
|
||||
if (typeof o.SetVariable != UNDEF) {
|
||||
r = o;
|
||||
}
|
||||
else {
|
||||
var n = o.getElementsByTagName(OBJECT)[0];
|
||||
if (n) {
|
||||
r = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Requirements for Adobe Express Install
|
||||
- only one instance can be active at a time
|
||||
- fp 6.0.65 or higher
|
||||
- Win/Mac OS only
|
||||
- no Webkit engines older than version 312
|
||||
*/
|
||||
function canExpressInstall() {
|
||||
return !isExpressInstallActive && hasPlayerVersion("6.0.65") && (ua.win || ua.mac) && !(ua.wk && ua.wk < 312);
|
||||
}
|
||||
|
||||
/* Show the Adobe Express Install dialog
|
||||
- Reference: http://www.adobe.com/cfusion/knowledgebase/index.cfm?id=6a253b75
|
||||
*/
|
||||
function showExpressInstall(att, par, replaceElemIdStr, callbackFn) {
|
||||
isExpressInstallActive = true;
|
||||
storedCallbackFn = callbackFn || null;
|
||||
storedCallbackObj = {success:false, id:replaceElemIdStr};
|
||||
var obj = getElementById(replaceElemIdStr);
|
||||
if (obj) {
|
||||
if (obj.nodeName == "OBJECT") { // static publishing
|
||||
storedAltContent = abstractAltContent(obj);
|
||||
storedAltContentId = null;
|
||||
}
|
||||
else { // dynamic publishing
|
||||
storedAltContent = obj;
|
||||
storedAltContentId = replaceElemIdStr;
|
||||
}
|
||||
att.id = EXPRESS_INSTALL_ID;
|
||||
if (typeof att.width == UNDEF || (!/%$/.test(att.width) && parseInt(att.width, 10) < 310)) { att.width = "310"; }
|
||||
if (typeof att.height == UNDEF || (!/%$/.test(att.height) && parseInt(att.height, 10) < 137)) { att.height = "137"; }
|
||||
doc.title = doc.title.slice(0, 47) + " - Flash Player Installation";
|
||||
var pt = ua.ie && ua.win ? "ActiveX" : "PlugIn",
|
||||
fv = "MMredirectURL=" + encodeURI(window.location).toString().replace(/&/g,"%26") + "&MMplayerType=" + pt + "&MMdoctitle=" + doc.title;
|
||||
if (typeof par.flashvars != UNDEF) {
|
||||
par.flashvars += "&" + fv;
|
||||
}
|
||||
else {
|
||||
par.flashvars = fv;
|
||||
}
|
||||
// IE only: when a SWF is loading (AND: not available in cache) wait for the readyState of the object element to become 4 before removing it,
|
||||
// because you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work
|
||||
if (ua.ie && ua.win && obj.readyState != 4) {
|
||||
var newObj = createElement("div");
|
||||
replaceElemIdStr += "SWFObjectNew";
|
||||
newObj.setAttribute("id", replaceElemIdStr);
|
||||
obj.parentNode.insertBefore(newObj, obj); // insert placeholder div that will be replaced by the object element that loads expressinstall.swf
|
||||
obj.style.display = "none";
|
||||
(function(){
|
||||
if (obj.readyState == 4) {
|
||||
obj.parentNode.removeChild(obj);
|
||||
}
|
||||
else {
|
||||
setTimeout(arguments.callee, 10);
|
||||
}
|
||||
})();
|
||||
}
|
||||
createSWF(att, par, replaceElemIdStr);
|
||||
}
|
||||
}
|
||||
|
||||
/* Functions to abstract and display alternative content
|
||||
*/
|
||||
function displayAltContent(obj) {
|
||||
if (ua.ie && ua.win && obj.readyState != 4) {
|
||||
// IE only: when a SWF is loading (AND: not available in cache) wait for the readyState of the object element to become 4 before removing it,
|
||||
// because you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work
|
||||
var el = createElement("div");
|
||||
obj.parentNode.insertBefore(el, obj); // insert placeholder div that will be replaced by the alternative content
|
||||
el.parentNode.replaceChild(abstractAltContent(obj), el);
|
||||
obj.style.display = "none";
|
||||
(function(){
|
||||
if (obj.readyState == 4) {
|
||||
obj.parentNode.removeChild(obj);
|
||||
}
|
||||
else {
|
||||
setTimeout(arguments.callee, 10);
|
||||
}
|
||||
})();
|
||||
}
|
||||
else {
|
||||
obj.parentNode.replaceChild(abstractAltContent(obj), obj);
|
||||
}
|
||||
}
|
||||
|
||||
function abstractAltContent(obj) {
|
||||
var ac = createElement("div");
|
||||
if (ua.win && ua.ie) {
|
||||
ac.innerHTML = obj.innerHTML;
|
||||
}
|
||||
else {
|
||||
var nestedObj = obj.getElementsByTagName(OBJECT)[0];
|
||||
if (nestedObj) {
|
||||
var c = nestedObj.childNodes;
|
||||
if (c) {
|
||||
var cl = c.length;
|
||||
for (var i = 0; i < cl; i++) {
|
||||
if (!(c[i].nodeType == 1 && c[i].nodeName == "PARAM") && !(c[i].nodeType == 8)) {
|
||||
ac.appendChild(c[i].cloneNode(true));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ac;
|
||||
}
|
||||
|
||||
/* Cross-browser dynamic SWF creation
|
||||
*/
|
||||
function createSWF(attObj, parObj, id) {
|
||||
var r, el = getElementById(id);
|
||||
if (ua.wk && ua.wk < 312) { return r; }
|
||||
if (el) {
|
||||
if (typeof attObj.id == UNDEF) { // if no 'id' is defined for the object element, it will inherit the 'id' from the alternative content
|
||||
attObj.id = id;
|
||||
}
|
||||
if (ua.ie && ua.win) { // Internet Explorer + the HTML object element + W3C DOM methods do not combine: fall back to outerHTML
|
||||
var att = "";
|
||||
for (var i in attObj) {
|
||||
if (attObj[i] != Object.prototype[i]) { // filter out prototype additions from other potential libraries
|
||||
if (i.toLowerCase() == "data") {
|
||||
parObj.movie = attObj[i];
|
||||
}
|
||||
else if (i.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword
|
||||
att += ' class="' + attObj[i] + '"';
|
||||
}
|
||||
else if (i.toLowerCase() != "classid") {
|
||||
att += ' ' + i + '="' + attObj[i] + '"';
|
||||
}
|
||||
}
|
||||
}
|
||||
var par = "";
|
||||
for (var j in parObj) {
|
||||
if (parObj[j] != Object.prototype[j]) { // filter out prototype additions from other potential libraries
|
||||
par += '<param name="' + j + '" value="' + parObj[j] + '" />';
|
||||
}
|
||||
}
|
||||
el.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' + att + '>' + par + '</object>';
|
||||
objIdArr[objIdArr.length] = attObj.id; // stored to fix object 'leaks' on unload (dynamic publishing only)
|
||||
r = getElementById(attObj.id);
|
||||
}
|
||||
else { // well-behaving browsers
|
||||
var o = createElement(OBJECT);
|
||||
o.setAttribute("type", FLASH_MIME_TYPE);
|
||||
for (var m in attObj) {
|
||||
if (attObj[m] != Object.prototype[m]) { // filter out prototype additions from other potential libraries
|
||||
if (m.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword
|
||||
o.setAttribute("class", attObj[m]);
|
||||
}
|
||||
else if (m.toLowerCase() != "classid") { // filter out IE specific attribute
|
||||
o.setAttribute(m, attObj[m]);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (var n in parObj) {
|
||||
if (parObj[n] != Object.prototype[n] && n.toLowerCase() != "movie") { // filter out prototype additions from other potential libraries and IE specific param element
|
||||
createObjParam(o, n, parObj[n]);
|
||||
}
|
||||
}
|
||||
el.parentNode.replaceChild(o, el);
|
||||
r = o;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
function createObjParam(el, pName, pValue) {
|
||||
var p = createElement("param");
|
||||
p.setAttribute("name", pName);
|
||||
p.setAttribute("value", pValue);
|
||||
el.appendChild(p);
|
||||
}
|
||||
|
||||
/* Cross-browser SWF removal
|
||||
- Especially needed to safely and completely remove a SWF in Internet Explorer
|
||||
*/
|
||||
function removeSWF(id) {
|
||||
var obj = getElementById(id);
|
||||
if (obj && obj.nodeName == "OBJECT") {
|
||||
if (ua.ie && ua.win) {
|
||||
obj.style.display = "none";
|
||||
(function(){
|
||||
if (obj.readyState == 4) {
|
||||
removeObjectInIE(id);
|
||||
}
|
||||
else {
|
||||
setTimeout(arguments.callee, 10);
|
||||
}
|
||||
})();
|
||||
}
|
||||
else {
|
||||
obj.parentNode.removeChild(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function removeObjectInIE(id) {
|
||||
var obj = getElementById(id);
|
||||
if (obj) {
|
||||
for (var i in obj) {
|
||||
if (typeof obj[i] == "function") {
|
||||
obj[i] = null;
|
||||
}
|
||||
}
|
||||
obj.parentNode.removeChild(obj);
|
||||
}
|
||||
}
|
||||
|
||||
/* Functions to optimize JavaScript compression
|
||||
*/
|
||||
function getElementById(id) {
|
||||
var el = null;
|
||||
try {
|
||||
el = doc.getElementById(id);
|
||||
}
|
||||
catch (e) {}
|
||||
return el;
|
||||
}
|
||||
|
||||
function createElement(el) {
|
||||
return doc.createElement(el);
|
||||
}
|
||||
|
||||
/* Updated attachEvent function for Internet Explorer
|
||||
- Stores attachEvent information in an Array, so on unload the detachEvent functions can be called to avoid memory leaks
|
||||
*/
|
||||
function addListener(target, eventType, fn) {
|
||||
target.attachEvent(eventType, fn);
|
||||
listenersArr[listenersArr.length] = [target, eventType, fn];
|
||||
}
|
||||
|
||||
/* Flash Player and SWF content version matching
|
||||
*/
|
||||
function hasPlayerVersion(rv) {
|
||||
var pv = ua.pv, v = rv.split(".");
|
||||
v[0] = parseInt(v[0], 10);
|
||||
v[1] = parseInt(v[1], 10) || 0; // supports short notation, e.g. "9" instead of "9.0.0"
|
||||
v[2] = parseInt(v[2], 10) || 0;
|
||||
return (pv[0] > v[0] || (pv[0] == v[0] && pv[1] > v[1]) || (pv[0] == v[0] && pv[1] == v[1] && pv[2] >= v[2])) ? true : false;
|
||||
}
|
||||
|
||||
/* Cross-browser dynamic CSS creation
|
||||
- Based on Bobby van der Sluis' solution: http://www.bobbyvandersluis.com/articles/dynamicCSS.php
|
||||
*/
|
||||
function createCSS(sel, decl, media, newStyle) {
|
||||
if (ua.ie && ua.mac) { return; }
|
||||
var h = doc.getElementsByTagName("head")[0];
|
||||
if (!h) { return; } // to also support badly authored HTML pages that lack a head element
|
||||
var m = (media && typeof media == "string") ? media : "screen";
|
||||
if (newStyle) {
|
||||
dynamicStylesheet = null;
|
||||
dynamicStylesheetMedia = null;
|
||||
}
|
||||
if (!dynamicStylesheet || dynamicStylesheetMedia != m) {
|
||||
// create dynamic stylesheet + get a global reference to it
|
||||
var s = createElement("style");
|
||||
s.setAttribute("type", "text/css");
|
||||
s.setAttribute("media", m);
|
||||
dynamicStylesheet = h.appendChild(s);
|
||||
if (ua.ie && ua.win && typeof doc.styleSheets != UNDEF && doc.styleSheets.length > 0) {
|
||||
dynamicStylesheet = doc.styleSheets[doc.styleSheets.length - 1];
|
||||
}
|
||||
dynamicStylesheetMedia = m;
|
||||
}
|
||||
// add style rule
|
||||
if (ua.ie && ua.win) {
|
||||
if (dynamicStylesheet && typeof dynamicStylesheet.addRule == OBJECT) {
|
||||
dynamicStylesheet.addRule(sel, decl);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (dynamicStylesheet && typeof doc.createTextNode != UNDEF) {
|
||||
dynamicStylesheet.appendChild(doc.createTextNode(sel + " {" + decl + "}"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setVisibility(id, isVisible) {
|
||||
if (!autoHideShow) { return; }
|
||||
var v = isVisible ? "visible" : "hidden";
|
||||
if (isDomLoaded && getElementById(id)) {
|
||||
getElementById(id).style.visibility = v;
|
||||
}
|
||||
else {
|
||||
createCSS("#" + id, "visibility:" + v);
|
||||
}
|
||||
}
|
||||
|
||||
/* Filter to avoid XSS attacks
|
||||
*/
|
||||
function urlEncodeIfNecessary(s) {
|
||||
var regex = /[\\\"<>\.;]/;
|
||||
var hasBadChars = regex.exec(s) != null;
|
||||
return hasBadChars && typeof encodeURIComponent != UNDEF ? encodeURIComponent(s) : s;
|
||||
}
|
||||
|
||||
/* Release memory to avoid memory leaks caused by closures, fix hanging audio/video threads and force open sockets/NetConnections to disconnect (Internet Explorer only)
|
||||
*/
|
||||
var cleanup = function() {
|
||||
if (ua.ie && ua.win) {
|
||||
window.attachEvent("onunload", function() {
|
||||
// remove listeners to avoid memory leaks
|
||||
var ll = listenersArr.length;
|
||||
for (var i = 0; i < ll; i++) {
|
||||
listenersArr[i][0].detachEvent(listenersArr[i][1], listenersArr[i][2]);
|
||||
}
|
||||
// cleanup dynamically embedded objects to fix audio/video threads and force open sockets and NetConnections to disconnect
|
||||
var il = objIdArr.length;
|
||||
for (var j = 0; j < il; j++) {
|
||||
removeSWF(objIdArr[j]);
|
||||
}
|
||||
// cleanup library's main closures to avoid memory leaks
|
||||
for (var k in ua) {
|
||||
ua[k] = null;
|
||||
}
|
||||
ua = null;
|
||||
for (var l in swfobject) {
|
||||
swfobject[l] = null;
|
||||
}
|
||||
swfobject = null;
|
||||
});
|
||||
}
|
||||
}();
|
||||
|
||||
return {
|
||||
/* Public API
|
||||
- Reference: http://code.google.com/p/swfobject/wiki/documentation
|
||||
*/
|
||||
registerObject: function(objectIdStr, swfVersionStr, xiSwfUrlStr, callbackFn) {
|
||||
if (ua.w3 && objectIdStr && swfVersionStr) {
|
||||
var regObj = {};
|
||||
regObj.id = objectIdStr;
|
||||
regObj.swfVersion = swfVersionStr;
|
||||
regObj.expressInstall = xiSwfUrlStr;
|
||||
regObj.callbackFn = callbackFn;
|
||||
regObjArr[regObjArr.length] = regObj;
|
||||
setVisibility(objectIdStr, false);
|
||||
}
|
||||
else if (callbackFn) {
|
||||
callbackFn({success:false, id:objectIdStr});
|
||||
}
|
||||
},
|
||||
|
||||
getObjectById: function(objectIdStr) {
|
||||
if (ua.w3) {
|
||||
return getObjectById(objectIdStr);
|
||||
}
|
||||
},
|
||||
|
||||
embedSWF: function(swfUrlStr, replaceElemIdStr, widthStr, heightStr, swfVersionStr, xiSwfUrlStr, flashvarsObj, parObj, attObj, callbackFn) {
|
||||
var callbackObj = {success:false, id:replaceElemIdStr};
|
||||
if (ua.w3 && !(ua.wk && ua.wk < 312) && swfUrlStr && replaceElemIdStr && widthStr && heightStr && swfVersionStr) {
|
||||
setVisibility(replaceElemIdStr, false);
|
||||
addDomLoadEvent(function() {
|
||||
widthStr += ""; // auto-convert to string
|
||||
heightStr += "";
|
||||
var att = {};
|
||||
if (attObj && typeof attObj === OBJECT) {
|
||||
for (var i in attObj) { // copy object to avoid the use of references, because web authors often reuse attObj for multiple SWFs
|
||||
att[i] = attObj[i];
|
||||
}
|
||||
}
|
||||
att.data = swfUrlStr;
|
||||
att.width = widthStr;
|
||||
att.height = heightStr;
|
||||
var par = {};
|
||||
if (parObj && typeof parObj === OBJECT) {
|
||||
for (var j in parObj) { // copy object to avoid the use of references, because web authors often reuse parObj for multiple SWFs
|
||||
par[j] = parObj[j];
|
||||
}
|
||||
}
|
||||
if (flashvarsObj && typeof flashvarsObj === OBJECT) {
|
||||
for (var k in flashvarsObj) { // copy object to avoid the use of references, because web authors often reuse flashvarsObj for multiple SWFs
|
||||
if (typeof par.flashvars != UNDEF) {
|
||||
par.flashvars += "&" + k + "=" + flashvarsObj[k];
|
||||
}
|
||||
else {
|
||||
par.flashvars = k + "=" + flashvarsObj[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hasPlayerVersion(swfVersionStr)) { // create SWF
|
||||
var obj = createSWF(att, par, replaceElemIdStr);
|
||||
if (att.id == replaceElemIdStr) {
|
||||
setVisibility(replaceElemIdStr, true);
|
||||
}
|
||||
callbackObj.success = true;
|
||||
callbackObj.ref = obj;
|
||||
}
|
||||
else if (xiSwfUrlStr && canExpressInstall()) { // show Adobe Express Install
|
||||
att.data = xiSwfUrlStr;
|
||||
showExpressInstall(att, par, replaceElemIdStr, callbackFn);
|
||||
return;
|
||||
}
|
||||
else { // show alternative content
|
||||
setVisibility(replaceElemIdStr, true);
|
||||
}
|
||||
if (callbackFn) { callbackFn(callbackObj); }
|
||||
});
|
||||
}
|
||||
else if (callbackFn) { callbackFn(callbackObj); }
|
||||
},
|
||||
|
||||
switchOffAutoHideShow: function() {
|
||||
autoHideShow = false;
|
||||
},
|
||||
|
||||
ua: ua,
|
||||
|
||||
getFlashPlayerVersion: function() {
|
||||
return { major:ua.pv[0], minor:ua.pv[1], release:ua.pv[2] };
|
||||
},
|
||||
|
||||
hasFlashPlayerVersion: hasPlayerVersion,
|
||||
|
||||
createSWF: function(attObj, parObj, replaceElemIdStr) {
|
||||
if (ua.w3) {
|
||||
return createSWF(attObj, parObj, replaceElemIdStr);
|
||||
}
|
||||
else {
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
|
||||
showExpressInstall: function(att, par, replaceElemIdStr, callbackFn) {
|
||||
if (ua.w3 && canExpressInstall()) {
|
||||
showExpressInstall(att, par, replaceElemIdStr, callbackFn);
|
||||
}
|
||||
},
|
||||
|
||||
removeSWF: function(objElemIdStr) {
|
||||
if (ua.w3) {
|
||||
removeSWF(objElemIdStr);
|
||||
}
|
||||
},
|
||||
|
||||
createCSS: function(selStr, declStr, mediaStr, newStyleBoolean) {
|
||||
if (ua.w3) {
|
||||
createCSS(selStr, declStr, mediaStr, newStyleBoolean);
|
||||
}
|
||||
},
|
||||
|
||||
addDomLoadEvent: addDomLoadEvent,
|
||||
|
||||
addLoadEvent: addLoadEvent,
|
||||
|
||||
getQueryParamValue: function(param) {
|
||||
var q = doc.location.search || doc.location.hash;
|
||||
if (q) {
|
||||
if (/\?/.test(q)) { q = q.split("?")[1]; } // strip question mark
|
||||
if (param == null) {
|
||||
return urlEncodeIfNecessary(q);
|
||||
}
|
||||
var pairs = q.split("&");
|
||||
for (var i = 0; i < pairs.length; i++) {
|
||||
if (pairs[i].substring(0, pairs[i].indexOf("=")) == param) {
|
||||
return urlEncodeIfNecessary(pairs[i].substring((pairs[i].indexOf("=") + 1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
return "";
|
||||
},
|
||||
|
||||
// For internal usage only
|
||||
expressInstallCallback: function() {
|
||||
if (isExpressInstallActive) {
|
||||
var obj = getElementById(EXPRESS_INSTALL_ID);
|
||||
if (obj && storedAltContent) {
|
||||
obj.parentNode.replaceChild(storedAltContent, obj);
|
||||
if (storedAltContentId) {
|
||||
setVisibility(storedAltContentId, true);
|
||||
if (ua.ie && ua.win) { storedAltContent.style.display = "block"; }
|
||||
}
|
||||
if (storedCallbackFn) { storedCallbackFn(storedCallbackObj); }
|
||||
}
|
||||
isExpressInstallActive = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}();
|
@ -1,108 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<!-- saved from url=(0014)about:internet -->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
|
||||
<!--
|
||||
Smart developers always View Source.
|
||||
|
||||
This application was built using Adobe Flex, an open source framework
|
||||
for building rich Internet applications that get delivered via the
|
||||
Flash Player or to desktops via Adobe AIR.
|
||||
|
||||
Learn more about Flex at http://flex.org
|
||||
// -->
|
||||
<head>
|
||||
<title></title>
|
||||
<meta name="google" value="notranslate" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<!-- Include CSS to eliminate any default margins/padding and set the height of the html element and
|
||||
the body element to 100%, because Firefox, or any Gecko based browser, interprets percentage as
|
||||
the percentage of the height of its parent container, which has to be set explicitly. Fix for
|
||||
Firefox 3.6 focus border issues. Initially, don't display flashContent div so it won't show
|
||||
if JavaScript disabled.
|
||||
-->
|
||||
<style type="text/css" media="screen">
|
||||
html, body { height:100%; }
|
||||
body { margin:0; padding:0; overflow:auto; text-align:center;
|
||||
background-color: #ffffff; }
|
||||
object:focus { outline:none; }
|
||||
#flashContent { display:none; }
|
||||
</style>
|
||||
|
||||
<!-- Enable Browser History by replacing useBrowserHistory tokens with two hyphens -->
|
||||
<!-- BEGIN Browser History required section -->
|
||||
<link rel="stylesheet" type="text/css" href="history/history.css" />
|
||||
<script type="text/javascript" src="history/history.js"></script>
|
||||
<!-- END Browser History required section -->
|
||||
|
||||
<script type="text/javascript" src="swfobject.js"></script>
|
||||
<script type="text/javascript">
|
||||
// For version detection, set to min. required Flash Player version, or 0 (or 0.0.0), for no version detection.
|
||||
var swfVersionStr = "11.4.0";
|
||||
// To use express install, set to playerProductInstall.swf, otherwise the empty string.
|
||||
var xiSwfUrlStr = "playerProductInstall.swf";
|
||||
var flashvars = {};
|
||||
var params = {};
|
||||
params.quality = "high";
|
||||
params.bgcolor = "#ffffff";
|
||||
params.allowscriptaccess = "sameDomain";
|
||||
params.allowfullscreen = "true";
|
||||
var attributes = {};
|
||||
attributes.id = "CIMBridge";
|
||||
attributes.name = "CIMBridge";
|
||||
attributes.align = "middle";
|
||||
swfobject.embedSWF(
|
||||
"CIMBridge.swf", "flashContent",
|
||||
"100%", "100%",
|
||||
swfVersionStr, xiSwfUrlStr,
|
||||
flashvars, params, attributes);
|
||||
// JavaScript enabled so display the flashContent div in case it is not replaced with a swf object.
|
||||
swfobject.createCSS("#flashContent", "display:block;text-align:left;");
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- SWFObject's dynamic embed method replaces this alternative HTML content with Flash content when enough
|
||||
JavaScript and Flash plug-in support is available. The div is initially hidden so that it doesn't show
|
||||
when JavaScript is disabled.
|
||||
-->
|
||||
<div id="flashContent">
|
||||
<p>
|
||||
To view this page ensure that Adobe Flash Player version
|
||||
11.4.0 or greater is installed.
|
||||
</p>
|
||||
<script type="text/javascript">
|
||||
var pageHost = ((document.location.protocol == "https:") ? "https://" : "http://");
|
||||
document.write("<a href='http://www.adobe.com/go/getflashplayer'><img src='"
|
||||
+ pageHost + "www.adobe.com/images/shared/download_buttons/get_flash_player.gif' alt='Get Adobe Flash player' /></a>" );
|
||||
</script>
|
||||
</div>
|
||||
|
||||
<noscript>
|
||||
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="100%" height="100%" id="CIMBridge">
|
||||
<param name="movie" value="CIMBridge.swf" />
|
||||
<param name="quality" value="high" />
|
||||
<param name="bgcolor" value="#ffffff" />
|
||||
<param name="allowScriptAccess" value="sameDomain" />
|
||||
<param name="allowFullScreen" value="true" />
|
||||
<!--[if !IE]>-->
|
||||
<object type="application/x-shockwave-flash" data="CIMBridge.swf" width="100%" height="100%">
|
||||
<param name="quality" value="high" />
|
||||
<param name="bgcolor" value="#ffffff" />
|
||||
<param name="allowScriptAccess" value="sameDomain" />
|
||||
<param name="allowFullScreen" value="true" />
|
||||
<!--<![endif]-->
|
||||
<!--[if gte IE 6]>-->
|
||||
<p>
|
||||
Either scripts and active content are not permitted to run or Adobe Flash Player version
|
||||
11.4.0 or greater is not installed.
|
||||
</p>
|
||||
<!--<![endif]-->
|
||||
<a href="http://www.adobe.com/go/getflashplayer">
|
||||
<img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash Player" />
|
||||
</a>
|
||||
<!--[if !IE]>-->
|
||||
</object>
|
||||
<!--<![endif]-->
|
||||
</object>
|
||||
</noscript>
|
||||
</body>
|
||||
</html>
|
@ -1,6 +0,0 @@
|
||||
/* This CSS stylesheet defines styles used by required elements in a flex application page that supports browser history */
|
||||
|
||||
#ie_historyFrame { width: 0px; height: 0px; display:none }
|
||||
#firefox_anchorDiv { width: 0px; height: 0px; display:none }
|
||||
#safari_formDiv { width: 0px; height: 0px; display:none }
|
||||
#safari_rememberDiv { width: 0px; height: 0px; display:none }
|
@ -1,678 +0,0 @@
|
||||
BrowserHistoryUtils = {
|
||||
addEvent: function(elm, evType, fn, useCapture) {
|
||||
useCapture = useCapture || false;
|
||||
if (elm.addEventListener) {
|
||||
elm.addEventListener(evType, fn, useCapture);
|
||||
return true;
|
||||
}
|
||||
else if (elm.attachEvent) {
|
||||
var r = elm.attachEvent('on' + evType, fn);
|
||||
return r;
|
||||
}
|
||||
else {
|
||||
elm['on' + evType] = fn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BrowserHistory = (function() {
|
||||
// type of browser
|
||||
var browser = {
|
||||
ie: false,
|
||||
ie8: false,
|
||||
firefox: false,
|
||||
safari: false,
|
||||
opera: false,
|
||||
version: -1
|
||||
};
|
||||
|
||||
// Default app state URL to use when no fragment ID present
|
||||
var defaultHash = '';
|
||||
|
||||
// Last-known app state URL
|
||||
var currentHref = document.location.href;
|
||||
|
||||
// Initial URL (used only by IE)
|
||||
var initialHref = document.location.href;
|
||||
|
||||
// Initial URL (used only by IE)
|
||||
var initialHash = document.location.hash;
|
||||
|
||||
// History frame source URL prefix (used only by IE)
|
||||
var historyFrameSourcePrefix = 'history/historyFrame.html?';
|
||||
|
||||
// History maintenance (used only by Safari)
|
||||
var currentHistoryLength = -1;
|
||||
|
||||
// Flag to denote the existence of onhashchange
|
||||
var browserHasHashChange = false;
|
||||
|
||||
var historyHash = [];
|
||||
|
||||
var initialState = createState(initialHref, initialHref + '#' + initialHash, initialHash);
|
||||
|
||||
var backStack = [];
|
||||
var forwardStack = [];
|
||||
|
||||
var currentObjectId = null;
|
||||
|
||||
//UserAgent detection
|
||||
var useragent = navigator.userAgent.toLowerCase();
|
||||
|
||||
if (useragent.indexOf("opera") != -1) {
|
||||
browser.opera = true;
|
||||
} else if (useragent.indexOf("msie") != -1) {
|
||||
browser.ie = true;
|
||||
browser.version = parseFloat(useragent.substring(useragent.indexOf('msie') + 4));
|
||||
if (browser.version == 8)
|
||||
{
|
||||
browser.ie = false;
|
||||
browser.ie8 = true;
|
||||
}
|
||||
} else if (useragent.indexOf("safari") != -1) {
|
||||
browser.safari = true;
|
||||
browser.version = parseFloat(useragent.substring(useragent.indexOf('safari') + 7));
|
||||
} else if (useragent.indexOf("gecko") != -1) {
|
||||
browser.firefox = true;
|
||||
}
|
||||
|
||||
if (browser.ie == true && browser.version == 7) {
|
||||
window["_ie_firstload"] = false;
|
||||
}
|
||||
|
||||
function hashChangeHandler()
|
||||
{
|
||||
currentHref = document.location.href;
|
||||
var flexAppUrl = getHash();
|
||||
//ADR: to fix multiple
|
||||
if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) {
|
||||
var pl = getPlayers();
|
||||
for (var i = 0; i < pl.length; i++) {
|
||||
pl[i].browserURLChange(flexAppUrl);
|
||||
}
|
||||
} else {
|
||||
getPlayer().browserURLChange(flexAppUrl);
|
||||
}
|
||||
}
|
||||
|
||||
// Accessor functions for obtaining specific elements of the page.
|
||||
function getHistoryFrame()
|
||||
{
|
||||
return document.getElementById('ie_historyFrame');
|
||||
}
|
||||
|
||||
function getFormElement()
|
||||
{
|
||||
return document.getElementById('safari_formDiv');
|
||||
}
|
||||
|
||||
function getRememberElement()
|
||||
{
|
||||
return document.getElementById("safari_remember_field");
|
||||
}
|
||||
|
||||
// Get the Flash player object for performing ExternalInterface callbacks.
|
||||
// Updated for changes to SWFObject2.
|
||||
function getPlayer(id) {
|
||||
var i;
|
||||
|
||||
if (id && document.getElementById(id)) {
|
||||
var r = document.getElementById(id);
|
||||
if (typeof r.SetVariable != "undefined") {
|
||||
return r;
|
||||
}
|
||||
else {
|
||||
var o = r.getElementsByTagName("object");
|
||||
var e = r.getElementsByTagName("embed");
|
||||
for (i = 0; i < o.length; i++) {
|
||||
if (typeof o[i].browserURLChange != "undefined")
|
||||
return o[i];
|
||||
}
|
||||
for (i = 0; i < e.length; i++) {
|
||||
if (typeof e[i].browserURLChange != "undefined")
|
||||
return e[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
var o = document.getElementsByTagName("object");
|
||||
var e = document.getElementsByTagName("embed");
|
||||
for (i = 0; i < e.length; i++) {
|
||||
if (typeof e[i].browserURLChange != "undefined")
|
||||
{
|
||||
return e[i];
|
||||
}
|
||||
}
|
||||
for (i = 0; i < o.length; i++) {
|
||||
if (typeof o[i].browserURLChange != "undefined")
|
||||
{
|
||||
return o[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getPlayers() {
|
||||
var i;
|
||||
var players = [];
|
||||
if (players.length == 0) {
|
||||
var tmp = document.getElementsByTagName('object');
|
||||
for (i = 0; i < tmp.length; i++)
|
||||
{
|
||||
if (typeof tmp[i].browserURLChange != "undefined")
|
||||
players.push(tmp[i]);
|
||||
}
|
||||
}
|
||||
if (players.length == 0 || players[0].object == null) {
|
||||
var tmp = document.getElementsByTagName('embed');
|
||||
for (i = 0; i < tmp.length; i++)
|
||||
{
|
||||
if (typeof tmp[i].browserURLChange != "undefined")
|
||||
players.push(tmp[i]);
|
||||
}
|
||||
}
|
||||
return players;
|
||||
}
|
||||
|
||||
function getIframeHash() {
|
||||
var doc = getHistoryFrame().contentWindow.document;
|
||||
var hash = String(doc.location.search);
|
||||
if (hash.length == 1 && hash.charAt(0) == "?") {
|
||||
hash = "";
|
||||
}
|
||||
else if (hash.length >= 2 && hash.charAt(0) == "?") {
|
||||
hash = hash.substring(1);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
/* Get the current location hash excluding the '#' symbol. */
|
||||
function getHash() {
|
||||
// It would be nice if we could use document.location.hash here,
|
||||
// but it's faulty sometimes.
|
||||
var idx = document.location.href.indexOf('#');
|
||||
return (idx >= 0) ? document.location.href.substr(idx+1) : '';
|
||||
}
|
||||
|
||||
/* Get the current location hash excluding the '#' symbol. */
|
||||
function setHash(hash) {
|
||||
// It would be nice if we could use document.location.hash here,
|
||||
// but it's faulty sometimes.
|
||||
if (hash == '') hash = '#'
|
||||
document.location.hash = hash;
|
||||
}
|
||||
|
||||
function createState(baseUrl, newUrl, flexAppUrl) {
|
||||
return { 'baseUrl': baseUrl, 'newUrl': newUrl, 'flexAppUrl': flexAppUrl, 'title': null };
|
||||
}
|
||||
|
||||
/* Add a history entry to the browser.
|
||||
* baseUrl: the portion of the location prior to the '#'
|
||||
* newUrl: the entire new URL, including '#' and following fragment
|
||||
* flexAppUrl: the portion of the location following the '#' only
|
||||
*/
|
||||
function addHistoryEntry(baseUrl, newUrl, flexAppUrl) {
|
||||
|
||||
//delete all the history entries
|
||||
forwardStack = [];
|
||||
|
||||
if (browser.ie) {
|
||||
//Check to see if we are being asked to do a navigate for the first
|
||||
//history entry, and if so ignore, because it's coming from the creation
|
||||
//of the history iframe
|
||||
if (flexAppUrl == defaultHash && document.location.href == initialHref && window['_ie_firstload']) {
|
||||
currentHref = initialHref;
|
||||
return;
|
||||
}
|
||||
if ((!flexAppUrl || flexAppUrl == defaultHash) && window['_ie_firstload']) {
|
||||
newUrl = baseUrl + '#' + defaultHash;
|
||||
flexAppUrl = defaultHash;
|
||||
} else {
|
||||
// for IE, tell the history frame to go somewhere without a '#'
|
||||
// in order to get this entry into the browser history.
|
||||
getHistoryFrame().src = historyFrameSourcePrefix + flexAppUrl;
|
||||
}
|
||||
setHash(flexAppUrl);
|
||||
} else {
|
||||
|
||||
//ADR
|
||||
if (backStack.length == 0 && initialState.flexAppUrl == flexAppUrl) {
|
||||
initialState = createState(baseUrl, newUrl, flexAppUrl);
|
||||
} else if(backStack.length > 0 && backStack[backStack.length - 1].flexAppUrl == flexAppUrl) {
|
||||
backStack[backStack.length - 1] = createState(baseUrl, newUrl, flexAppUrl);
|
||||
}
|
||||
|
||||
if (browser.safari && !browserHasHashChange) {
|
||||
// for Safari, submit a form whose action points to the desired URL
|
||||
if (browser.version <= 419.3) {
|
||||
var file = window.location.pathname.toString();
|
||||
file = file.substring(file.lastIndexOf("/")+1);
|
||||
getFormElement().innerHTML = '<form name="historyForm" action="'+file+'#' + flexAppUrl + '" method="GET"></form>';
|
||||
//get the current elements and add them to the form
|
||||
var qs = window.location.search.substring(1);
|
||||
var qs_arr = qs.split("&");
|
||||
for (var i = 0; i < qs_arr.length; i++) {
|
||||
var tmp = qs_arr[i].split("=");
|
||||
var elem = document.createElement("input");
|
||||
elem.type = "hidden";
|
||||
elem.name = tmp[0];
|
||||
elem.value = tmp[1];
|
||||
document.forms.historyForm.appendChild(elem);
|
||||
}
|
||||
document.forms.historyForm.submit();
|
||||
} else {
|
||||
top.location.hash = flexAppUrl;
|
||||
}
|
||||
// We also have to maintain the history by hand for Safari
|
||||
historyHash[history.length] = flexAppUrl;
|
||||
_storeStates();
|
||||
} else {
|
||||
// Otherwise, just tell the browser to go there
|
||||
setHash(flexAppUrl);
|
||||
}
|
||||
}
|
||||
backStack.push(createState(baseUrl, newUrl, flexAppUrl));
|
||||
}
|
||||
|
||||
function _storeStates() {
|
||||
if (browser.safari) {
|
||||
getRememberElement().value = historyHash.join(",");
|
||||
}
|
||||
}
|
||||
|
||||
function handleBackButton() {
|
||||
//The "current" page is always at the top of the history stack.
|
||||
var current = backStack.pop();
|
||||
if (!current) { return; }
|
||||
var last = backStack[backStack.length - 1];
|
||||
if (!last && backStack.length == 0){
|
||||
last = initialState;
|
||||
}
|
||||
forwardStack.push(current);
|
||||
}
|
||||
|
||||
function handleForwardButton() {
|
||||
//summary: private method. Do not call this directly.
|
||||
|
||||
var last = forwardStack.pop();
|
||||
if (!last) { return; }
|
||||
backStack.push(last);
|
||||
}
|
||||
|
||||
function handleArbitraryUrl() {
|
||||
//delete all the history entries
|
||||
forwardStack = [];
|
||||
}
|
||||
|
||||
/* Called periodically to poll to see if we need to detect navigation that has occurred */
|
||||
function checkForUrlChange() {
|
||||
|
||||
if (browser.ie) {
|
||||
if (currentHref != document.location.href && currentHref + '#' != document.location.href) {
|
||||
//This occurs when the user has navigated to a specific URL
|
||||
//within the app, and didn't use browser back/forward
|
||||
//IE seems to have a bug where it stops updating the URL it
|
||||
//shows the end-user at this point, but programatically it
|
||||
//appears to be correct. Do a full app reload to get around
|
||||
//this issue.
|
||||
if (browser.version < 7) {
|
||||
currentHref = document.location.href;
|
||||
document.location.reload();
|
||||
} else {
|
||||
if (getHash() != getIframeHash()) {
|
||||
// this.iframe.src = this.blankURL + hash;
|
||||
var sourceToSet = historyFrameSourcePrefix + getHash();
|
||||
getHistoryFrame().src = sourceToSet;
|
||||
currentHref = document.location.href;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (browser.safari && !browserHasHashChange) {
|
||||
// For Safari, we have to check to see if history.length changed.
|
||||
if (currentHistoryLength >= 0 && history.length != currentHistoryLength) {
|
||||
//alert("did change: " + history.length + ", " + historyHash.length + "|" + historyHash[history.length] + "|>" + historyHash.join("|"));
|
||||
var flexAppUrl = getHash();
|
||||
if (browser.version < 528.16 /* Anything earlier than Safari 4.0 */)
|
||||
{
|
||||
// If it did change and we're running Safari 3.x or earlier,
|
||||
// then we have to look the old state up in our hand-maintained
|
||||
// array since document.location.hash won't have changed,
|
||||
// then call back into BrowserManager.
|
||||
currentHistoryLength = history.length;
|
||||
flexAppUrl = historyHash[currentHistoryLength];
|
||||
}
|
||||
|
||||
//ADR: to fix multiple
|
||||
if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) {
|
||||
var pl = getPlayers();
|
||||
for (var i = 0; i < pl.length; i++) {
|
||||
pl[i].browserURLChange(flexAppUrl);
|
||||
}
|
||||
} else {
|
||||
getPlayer().browserURLChange(flexAppUrl);
|
||||
}
|
||||
_storeStates();
|
||||
}
|
||||
}
|
||||
if (browser.firefox && !browserHasHashChange) {
|
||||
if (currentHref != document.location.href) {
|
||||
var bsl = backStack.length;
|
||||
|
||||
var urlActions = {
|
||||
back: false,
|
||||
forward: false,
|
||||
set: false
|
||||
}
|
||||
|
||||
if ((window.location.hash == initialHash || window.location.href == initialHref) && (bsl == 1)) {
|
||||
urlActions.back = true;
|
||||
// FIXME: could this ever be a forward button?
|
||||
// we can't clear it because we still need to check for forwards. Ugg.
|
||||
// clearInterval(this.locationTimer);
|
||||
handleBackButton();
|
||||
}
|
||||
|
||||
// first check to see if we could have gone forward. We always halt on
|
||||
// a no-hash item.
|
||||
if (forwardStack.length > 0) {
|
||||
if (forwardStack[forwardStack.length-1].flexAppUrl == getHash()) {
|
||||
urlActions.forward = true;
|
||||
handleForwardButton();
|
||||
}
|
||||
}
|
||||
|
||||
// ok, that didn't work, try someplace back in the history stack
|
||||
if ((bsl >= 2) && (backStack[bsl - 2])) {
|
||||
if (backStack[bsl - 2].flexAppUrl == getHash()) {
|
||||
urlActions.back = true;
|
||||
handleBackButton();
|
||||
}
|
||||
}
|
||||
|
||||
if (!urlActions.back && !urlActions.forward) {
|
||||
var foundInStacks = {
|
||||
back: -1,
|
||||
forward: -1
|
||||
}
|
||||
|
||||
for (var i = 0; i < backStack.length; i++) {
|
||||
if (backStack[i].flexAppUrl == getHash() && i != (bsl - 2)) {
|
||||
arbitraryUrl = true;
|
||||
foundInStacks.back = i;
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < forwardStack.length; i++) {
|
||||
if (forwardStack[i].flexAppUrl == getHash() && i != (bsl - 2)) {
|
||||
arbitraryUrl = true;
|
||||
foundInStacks.forward = i;
|
||||
}
|
||||
}
|
||||
handleArbitraryUrl();
|
||||
}
|
||||
|
||||
// Firefox changed; do a callback into BrowserManager to tell it.
|
||||
currentHref = document.location.href;
|
||||
var flexAppUrl = getHash();
|
||||
//ADR: to fix multiple
|
||||
if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) {
|
||||
var pl = getPlayers();
|
||||
for (var i = 0; i < pl.length; i++) {
|
||||
pl[i].browserURLChange(flexAppUrl);
|
||||
}
|
||||
} else {
|
||||
getPlayer().browserURLChange(flexAppUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var _initialize = function () {
|
||||
|
||||
browserHasHashChange = ("onhashchange" in document.body);
|
||||
|
||||
if (browser.ie)
|
||||
{
|
||||
var scripts = document.getElementsByTagName('script');
|
||||
for (var i = 0, s; s = scripts[i]; i++) {
|
||||
if (s.src.indexOf("history.js") > -1) {
|
||||
var iframe_location = (new String(s.src)).replace("history.js", "historyFrame.html");
|
||||
}
|
||||
}
|
||||
historyFrameSourcePrefix = iframe_location + "?";
|
||||
var src = historyFrameSourcePrefix;
|
||||
|
||||
var iframe = document.createElement("iframe");
|
||||
iframe.id = 'ie_historyFrame';
|
||||
iframe.name = 'ie_historyFrame';
|
||||
iframe.src = 'javascript:false;';
|
||||
|
||||
try {
|
||||
document.body.appendChild(iframe);
|
||||
} catch(e) {
|
||||
setTimeout(function() {
|
||||
document.body.appendChild(iframe);
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (browser.safari && !browserHasHashChange)
|
||||
{
|
||||
var rememberDiv = document.createElement("div");
|
||||
rememberDiv.id = 'safari_rememberDiv';
|
||||
document.body.appendChild(rememberDiv);
|
||||
rememberDiv.innerHTML = '<input type="text" id="safari_remember_field" style="width: 500px;">';
|
||||
|
||||
var formDiv = document.createElement("div");
|
||||
formDiv.id = 'safari_formDiv';
|
||||
document.body.appendChild(formDiv);
|
||||
|
||||
var reloader_content = document.createElement('div');
|
||||
reloader_content.id = 'safarireloader';
|
||||
var scripts = document.getElementsByTagName('script');
|
||||
for (var i = 0, s; s = scripts[i]; i++) {
|
||||
if (s.src.indexOf("history.js") > -1) {
|
||||
html = (new String(s.src)).replace(".js", ".html");
|
||||
}
|
||||
}
|
||||
reloader_content.innerHTML = '<iframe id="safarireloader-iframe" src="about:blank" frameborder="no" scrolling="no"></iframe>';
|
||||
document.body.appendChild(reloader_content);
|
||||
reloader_content.style.position = 'absolute';
|
||||
reloader_content.style.left = reloader_content.style.top = '-9999px';
|
||||
iframe = reloader_content.getElementsByTagName('iframe')[0];
|
||||
|
||||
if (document.getElementById("safari_remember_field").value != "" ) {
|
||||
historyHash = document.getElementById("safari_remember_field").value.split(",");
|
||||
}
|
||||
}
|
||||
|
||||
if (browserHasHashChange)
|
||||
document.body.onhashchange = hashChangeHandler;
|
||||
}
|
||||
|
||||
return {
|
||||
historyHash: historyHash,
|
||||
backStack: function() { return backStack; },
|
||||
forwardStack: function() { return forwardStack },
|
||||
getPlayer: getPlayer,
|
||||
initialize: function(src) {
|
||||
_initialize(src);
|
||||
},
|
||||
setURL: function(url) {
|
||||
document.location.href = url;
|
||||
},
|
||||
getURL: function() {
|
||||
return document.location.href;
|
||||
},
|
||||
getTitle: function() {
|
||||
return document.title;
|
||||
},
|
||||
setTitle: function(title) {
|
||||
try {
|
||||
backStack[backStack.length - 1].title = title;
|
||||
} catch(e) { }
|
||||
//if on safari, set the title to be the empty string.
|
||||
if (browser.safari) {
|
||||
if (title == "") {
|
||||
try {
|
||||
var tmp = window.location.href.toString();
|
||||
title = tmp.substring((tmp.lastIndexOf("/")+1), tmp.lastIndexOf("#"));
|
||||
} catch(e) {
|
||||
title = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
document.title = title;
|
||||
},
|
||||
setDefaultURL: function(def)
|
||||
{
|
||||
defaultHash = def;
|
||||
def = getHash();
|
||||
//trailing ? is important else an extra frame gets added to the history
|
||||
//when navigating back to the first page. Alternatively could check
|
||||
//in history frame navigation to compare # and ?.
|
||||
if (browser.ie)
|
||||
{
|
||||
window['_ie_firstload'] = true;
|
||||
var sourceToSet = historyFrameSourcePrefix + def;
|
||||
var func = function() {
|
||||
getHistoryFrame().src = sourceToSet;
|
||||
window.location.replace("#" + def);
|
||||
setInterval(checkForUrlChange, 50);
|
||||
}
|
||||
try {
|
||||
func();
|
||||
} catch(e) {
|
||||
window.setTimeout(function() { func(); }, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (browser.safari)
|
||||
{
|
||||
currentHistoryLength = history.length;
|
||||
if (historyHash.length == 0) {
|
||||
historyHash[currentHistoryLength] = def;
|
||||
var newloc = "#" + def;
|
||||
window.location.replace(newloc);
|
||||
} else {
|
||||
//alert(historyHash[historyHash.length-1]);
|
||||
}
|
||||
setInterval(checkForUrlChange, 50);
|
||||
}
|
||||
|
||||
|
||||
if (browser.firefox || browser.opera)
|
||||
{
|
||||
var reg = new RegExp("#" + def + "$");
|
||||
if (window.location.toString().match(reg)) {
|
||||
} else {
|
||||
var newloc ="#" + def;
|
||||
window.location.replace(newloc);
|
||||
}
|
||||
setInterval(checkForUrlChange, 50);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
/* Set the current browser URL; called from inside BrowserManager to propagate
|
||||
* the application state out to the container.
|
||||
*/
|
||||
setBrowserURL: function(flexAppUrl, objectId) {
|
||||
if (browser.ie && typeof objectId != "undefined") {
|
||||
currentObjectId = objectId;
|
||||
}
|
||||
//fromIframe = fromIframe || false;
|
||||
//fromFlex = fromFlex || false;
|
||||
//alert("setBrowserURL: " + flexAppUrl);
|
||||
//flexAppUrl = (flexAppUrl == "") ? defaultHash : flexAppUrl ;
|
||||
|
||||
var pos = document.location.href.indexOf('#');
|
||||
var baseUrl = pos != -1 ? document.location.href.substr(0, pos) : document.location.href;
|
||||
var newUrl = baseUrl + '#' + flexAppUrl;
|
||||
|
||||
if (document.location.href != newUrl && document.location.href + '#' != newUrl) {
|
||||
currentHref = newUrl;
|
||||
addHistoryEntry(baseUrl, newUrl, flexAppUrl);
|
||||
currentHistoryLength = history.length;
|
||||
}
|
||||
},
|
||||
|
||||
browserURLChange: function(flexAppUrl) {
|
||||
var objectId = null;
|
||||
if (browser.ie && currentObjectId != null) {
|
||||
objectId = currentObjectId;
|
||||
}
|
||||
|
||||
if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) {
|
||||
var pl = getPlayers();
|
||||
for (var i = 0; i < pl.length; i++) {
|
||||
try {
|
||||
pl[i].browserURLChange(flexAppUrl);
|
||||
} catch(e) { }
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
getPlayer(objectId).browserURLChange(flexAppUrl);
|
||||
} catch(e) { }
|
||||
}
|
||||
|
||||
currentObjectId = null;
|
||||
},
|
||||
getUserAgent: function() {
|
||||
return navigator.userAgent;
|
||||
},
|
||||
getPlatform: function() {
|
||||
return navigator.platform;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
// Initialization
|
||||
|
||||
// Automated unit testing and other diagnostics
|
||||
|
||||
function setURL(url)
|
||||
{
|
||||
document.location.href = url;
|
||||
}
|
||||
|
||||
function backButton()
|
||||
{
|
||||
history.back();
|
||||
}
|
||||
|
||||
function forwardButton()
|
||||
{
|
||||
history.forward();
|
||||
}
|
||||
|
||||
function goForwardOrBackInHistory(step)
|
||||
{
|
||||
history.go(step);
|
||||
}
|
||||
|
||||
//BrowserHistoryUtils.addEvent(window, "load", function() { BrowserHistory.initialize(); });
|
||||
(function(i) {
|
||||
var u =navigator.userAgent;var e=/*@cc_on!@*/false;
|
||||
var st = setTimeout;
|
||||
if(/webkit/i.test(u)){
|
||||
st(function(){
|
||||
var dr=document.readyState;
|
||||
if(dr=="loaded"||dr=="complete"){i()}
|
||||
else{st(arguments.callee,10);}},10);
|
||||
} else if((/mozilla/i.test(u)&&!/(compati)/.test(u)) || (/opera/i.test(u))){
|
||||
document.addEventListener("DOMContentLoaded",i,false);
|
||||
} else if(e){
|
||||
(function(){
|
||||
var t=document.createElement('doc:rdy');
|
||||
try{t.doScroll('left');
|
||||
i();t=null;
|
||||
}catch(e){st(arguments.callee,0);}})();
|
||||
} else{
|
||||
window.onload=i;
|
||||
}
|
||||
})( function() {BrowserHistory.initialize();} );
|
@ -1,29 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
|
||||
<META HTTP-EQUIV="Expires" CONTENT="-1">
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
function processUrl()
|
||||
{
|
||||
|
||||
var pos = url.indexOf("?");
|
||||
url = pos != -1 ? url.substr(pos + 1) : "";
|
||||
if (!parent._ie_firstload) {
|
||||
parent.BrowserHistory.setBrowserURL(url);
|
||||
try {
|
||||
parent.BrowserHistory.browserURLChange(url);
|
||||
} catch(e) { }
|
||||
} else {
|
||||
parent._ie_firstload = false;
|
||||
}
|
||||
}
|
||||
|
||||
var url = document.location.href;
|
||||
processUrl();
|
||||
document.write(encodeURIComponent(url));
|
||||
</script>
|
||||
Hidden frame for Browser History support.
|
||||
</body>
|
||||
</html>
|
@ -1,777 +0,0 @@
|
||||
/*! SWFObject v2.2 <http://code.google.com/p/swfobject/>
|
||||
is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
|
||||
*/
|
||||
|
||||
var swfobject = function() {
|
||||
|
||||
var UNDEF = "undefined",
|
||||
OBJECT = "object",
|
||||
SHOCKWAVE_FLASH = "Shockwave Flash",
|
||||
SHOCKWAVE_FLASH_AX = "ShockwaveFlash.ShockwaveFlash",
|
||||
FLASH_MIME_TYPE = "application/x-shockwave-flash",
|
||||
EXPRESS_INSTALL_ID = "SWFObjectExprInst",
|
||||
ON_READY_STATE_CHANGE = "onreadystatechange",
|
||||
|
||||
win = window,
|
||||
doc = document,
|
||||
nav = navigator,
|
||||
|
||||
plugin = false,
|
||||
domLoadFnArr = [main],
|
||||
regObjArr = [],
|
||||
objIdArr = [],
|
||||
listenersArr = [],
|
||||
storedAltContent,
|
||||
storedAltContentId,
|
||||
storedCallbackFn,
|
||||
storedCallbackObj,
|
||||
isDomLoaded = false,
|
||||
isExpressInstallActive = false,
|
||||
dynamicStylesheet,
|
||||
dynamicStylesheetMedia,
|
||||
autoHideShow = true,
|
||||
|
||||
/* Centralized function for browser feature detection
|
||||
- User agent string detection is only used when no good alternative is possible
|
||||
- Is executed directly for optimal performance
|
||||
*/
|
||||
ua = function() {
|
||||
var w3cdom = typeof doc.getElementById != UNDEF && typeof doc.getElementsByTagName != UNDEF && typeof doc.createElement != UNDEF,
|
||||
u = nav.userAgent.toLowerCase(),
|
||||
p = nav.platform.toLowerCase(),
|
||||
windows = p ? /win/.test(p) : /win/.test(u),
|
||||
mac = p ? /mac/.test(p) : /mac/.test(u),
|
||||
webkit = /webkit/.test(u) ? parseFloat(u.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, "$1")) : false, // returns either the webkit version or false if not webkit
|
||||
ie = !+"\v1", // feature detection based on Andrea Giammarchi's solution: http://webreflection.blogspot.com/2009/01/32-bytes-to-know-if-your-browser-is-ie.html
|
||||
playerVersion = [0,0,0],
|
||||
d = null;
|
||||
if (typeof nav.plugins != UNDEF && typeof nav.plugins[SHOCKWAVE_FLASH] == OBJECT) {
|
||||
d = nav.plugins[SHOCKWAVE_FLASH].description;
|
||||
if (d && !(typeof nav.mimeTypes != UNDEF && nav.mimeTypes[FLASH_MIME_TYPE] && !nav.mimeTypes[FLASH_MIME_TYPE].enabledPlugin)) { // navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin indicates whether plug-ins are enabled or disabled in Safari 3+
|
||||
plugin = true;
|
||||
ie = false; // cascaded feature detection for Internet Explorer
|
||||
d = d.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
|
||||
playerVersion[0] = parseInt(d.replace(/^(.*)\..*$/, "$1"), 10);
|
||||
playerVersion[1] = parseInt(d.replace(/^.*\.(.*)\s.*$/, "$1"), 10);
|
||||
playerVersion[2] = /[a-zA-Z]/.test(d) ? parseInt(d.replace(/^.*[a-zA-Z]+(.*)$/, "$1"), 10) : 0;
|
||||
}
|
||||
}
|
||||
else if (typeof win.ActiveXObject != UNDEF) {
|
||||
try {
|
||||
var a = new ActiveXObject(SHOCKWAVE_FLASH_AX);
|
||||
if (a) { // a will return null when ActiveX is disabled
|
||||
d = a.GetVariable("$version");
|
||||
if (d) {
|
||||
ie = true; // cascaded feature detection for Internet Explorer
|
||||
d = d.split(" ")[1].split(",");
|
||||
playerVersion = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(e) {}
|
||||
}
|
||||
return { w3:w3cdom, pv:playerVersion, wk:webkit, ie:ie, win:windows, mac:mac };
|
||||
}(),
|
||||
|
||||
/* Cross-browser onDomLoad
|
||||
- Will fire an event as soon as the DOM of a web page is loaded
|
||||
- Internet Explorer workaround based on Diego Perini's solution: http://javascript.nwbox.com/IEContentLoaded/
|
||||
- Regular onload serves as fallback
|
||||
*/
|
||||
onDomLoad = function() {
|
||||
if (!ua.w3) { return; }
|
||||
if ((typeof doc.readyState != UNDEF && doc.readyState == "complete") || (typeof doc.readyState == UNDEF && (doc.getElementsByTagName("body")[0] || doc.body))) { // function is fired after onload, e.g. when script is inserted dynamically
|
||||
callDomLoadFunctions();
|
||||
}
|
||||
if (!isDomLoaded) {
|
||||
if (typeof doc.addEventListener != UNDEF) {
|
||||
doc.addEventListener("DOMContentLoaded", callDomLoadFunctions, false);
|
||||
}
|
||||
if (ua.ie && ua.win) {
|
||||
doc.attachEvent(ON_READY_STATE_CHANGE, function() {
|
||||
if (doc.readyState == "complete") {
|
||||
doc.detachEvent(ON_READY_STATE_CHANGE, arguments.callee);
|
||||
callDomLoadFunctions();
|
||||
}
|
||||
});
|
||||
if (win == top) { // if not inside an iframe
|
||||
(function(){
|
||||
if (isDomLoaded) { return; }
|
||||
try {
|
||||
doc.documentElement.doScroll("left");
|
||||
}
|
||||
catch(e) {
|
||||
setTimeout(arguments.callee, 0);
|
||||
return;
|
||||
}
|
||||
callDomLoadFunctions();
|
||||
})();
|
||||
}
|
||||
}
|
||||
if (ua.wk) {
|
||||
(function(){
|
||||
if (isDomLoaded) { return; }
|
||||
if (!/loaded|complete/.test(doc.readyState)) {
|
||||
setTimeout(arguments.callee, 0);
|
||||
return;
|
||||
}
|
||||
callDomLoadFunctions();
|
||||
})();
|
||||
}
|
||||
addLoadEvent(callDomLoadFunctions);
|
||||
}
|
||||
}();
|
||||
|
||||
function callDomLoadFunctions() {
|
||||
if (isDomLoaded) { return; }
|
||||
try { // test if we can really add/remove elements to/from the DOM; we don't want to fire it too early
|
||||
var t = doc.getElementsByTagName("body")[0].appendChild(createElement("span"));
|
||||
t.parentNode.removeChild(t);
|
||||
}
|
||||
catch (e) { return; }
|
||||
isDomLoaded = true;
|
||||
var dl = domLoadFnArr.length;
|
||||
for (var i = 0; i < dl; i++) {
|
||||
domLoadFnArr[i]();
|
||||
}
|
||||
}
|
||||
|
||||
function addDomLoadEvent(fn) {
|
||||
if (isDomLoaded) {
|
||||
fn();
|
||||
}
|
||||
else {
|
||||
domLoadFnArr[domLoadFnArr.length] = fn; // Array.push() is only available in IE5.5+
|
||||
}
|
||||
}
|
||||
|
||||
/* Cross-browser onload
|
||||
- Based on James Edwards' solution: http://brothercake.com/site/resources/scripts/onload/
|
||||
- Will fire an event as soon as a web page including all of its assets are loaded
|
||||
*/
|
||||
function addLoadEvent(fn) {
|
||||
if (typeof win.addEventListener != UNDEF) {
|
||||
win.addEventListener("load", fn, false);
|
||||
}
|
||||
else if (typeof doc.addEventListener != UNDEF) {
|
||||
doc.addEventListener("load", fn, false);
|
||||
}
|
||||
else if (typeof win.attachEvent != UNDEF) {
|
||||
addListener(win, "onload", fn);
|
||||
}
|
||||
else if (typeof win.onload == "function") {
|
||||
var fnOld = win.onload;
|
||||
win.onload = function() {
|
||||
fnOld();
|
||||
fn();
|
||||
};
|
||||
}
|
||||
else {
|
||||
win.onload = fn;
|
||||
}
|
||||
}
|
||||
|
||||
/* Main function
|
||||
- Will preferably execute onDomLoad, otherwise onload (as a fallback)
|
||||
*/
|
||||
function main() {
|
||||
if (plugin) {
|
||||
testPlayerVersion();
|
||||
}
|
||||
else {
|
||||
matchVersions();
|
||||
}
|
||||
}
|
||||
|
||||
/* Detect the Flash Player version for non-Internet Explorer browsers
|
||||
- Detecting the plug-in version via the object element is more precise than using the plugins collection item's description:
|
||||
a. Both release and build numbers can be detected
|
||||
b. Avoid wrong descriptions by corrupt installers provided by Adobe
|
||||
c. Avoid wrong descriptions by multiple Flash Player entries in the plugin Array, caused by incorrect browser imports
|
||||
- Disadvantage of this method is that it depends on the availability of the DOM, while the plugins collection is immediately available
|
||||
*/
|
||||
function testPlayerVersion() {
|
||||
var b = doc.getElementsByTagName("body")[0];
|
||||
var o = createElement(OBJECT);
|
||||
o.setAttribute("type", FLASH_MIME_TYPE);
|
||||
var t = b.appendChild(o);
|
||||
if (t) {
|
||||
var counter = 0;
|
||||
(function(){
|
||||
if (typeof t.GetVariable != UNDEF) {
|
||||
var d = t.GetVariable("$version");
|
||||
if (d) {
|
||||
d = d.split(" ")[1].split(",");
|
||||
ua.pv = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
|
||||
}
|
||||
}
|
||||
else if (counter < 10) {
|
||||
counter++;
|
||||
setTimeout(arguments.callee, 10);
|
||||
return;
|
||||
}
|
||||
b.removeChild(o);
|
||||
t = null;
|
||||
matchVersions();
|
||||
})();
|
||||
}
|
||||
else {
|
||||
matchVersions();
|
||||
}
|
||||
}
|
||||
|
||||
/* Perform Flash Player and SWF version matching; static publishing only
|
||||
*/
|
||||
function matchVersions() {
|
||||
var rl = regObjArr.length;
|
||||
if (rl > 0) {
|
||||
for (var i = 0; i < rl; i++) { // for each registered object element
|
||||
var id = regObjArr[i].id;
|
||||
var cb = regObjArr[i].callbackFn;
|
||||
var cbObj = {success:false, id:id};
|
||||
if (ua.pv[0] > 0) {
|
||||
var obj = getElementById(id);
|
||||
if (obj) {
|
||||
if (hasPlayerVersion(regObjArr[i].swfVersion) && !(ua.wk && ua.wk < 312)) { // Flash Player version >= published SWF version: Houston, we have a match!
|
||||
setVisibility(id, true);
|
||||
if (cb) {
|
||||
cbObj.success = true;
|
||||
cbObj.ref = getObjectById(id);
|
||||
cb(cbObj);
|
||||
}
|
||||
}
|
||||
else if (regObjArr[i].expressInstall && canExpressInstall()) { // show the Adobe Express Install dialog if set by the web page author and if supported
|
||||
var att = {};
|
||||
att.data = regObjArr[i].expressInstall;
|
||||
att.width = obj.getAttribute("width") || "0";
|
||||
att.height = obj.getAttribute("height") || "0";
|
||||
if (obj.getAttribute("class")) { att.styleclass = obj.getAttribute("class"); }
|
||||
if (obj.getAttribute("align")) { att.align = obj.getAttribute("align"); }
|
||||
// parse HTML object param element's name-value pairs
|
||||
var par = {};
|
||||
var p = obj.getElementsByTagName("param");
|
||||
var pl = p.length;
|
||||
for (var j = 0; j < pl; j++) {
|
||||
if (p[j].getAttribute("name").toLowerCase() != "movie") {
|
||||
par[p[j].getAttribute("name")] = p[j].getAttribute("value");
|
||||
}
|
||||
}
|
||||
showExpressInstall(att, par, id, cb);
|
||||
}
|
||||
else { // Flash Player and SWF version mismatch or an older Webkit engine that ignores the HTML object element's nested param elements: display alternative content instead of SWF
|
||||
displayAltContent(obj);
|
||||
if (cb) { cb(cbObj); }
|
||||
}
|
||||
}
|
||||
}
|
||||
else { // if no Flash Player is installed or the fp version cannot be detected we let the HTML object element do its job (either show a SWF or alternative content)
|
||||
setVisibility(id, true);
|
||||
if (cb) {
|
||||
var o = getObjectById(id); // test whether there is an HTML object element or not
|
||||
if (o && typeof o.SetVariable != UNDEF) {
|
||||
cbObj.success = true;
|
||||
cbObj.ref = o;
|
||||
}
|
||||
cb(cbObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getObjectById(objectIdStr) {
|
||||
var r = null;
|
||||
var o = getElementById(objectIdStr);
|
||||
if (o && o.nodeName == "OBJECT") {
|
||||
if (typeof o.SetVariable != UNDEF) {
|
||||
r = o;
|
||||
}
|
||||
else {
|
||||
var n = o.getElementsByTagName(OBJECT)[0];
|
||||
if (n) {
|
||||
r = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Requirements for Adobe Express Install
|
||||
- only one instance can be active at a time
|
||||
- fp 6.0.65 or higher
|
||||
- Win/Mac OS only
|
||||
- no Webkit engines older than version 312
|
||||
*/
|
||||
function canExpressInstall() {
|
||||
return !isExpressInstallActive && hasPlayerVersion("6.0.65") && (ua.win || ua.mac) && !(ua.wk && ua.wk < 312);
|
||||
}
|
||||
|
||||
/* Show the Adobe Express Install dialog
|
||||
- Reference: http://www.adobe.com/cfusion/knowledgebase/index.cfm?id=6a253b75
|
||||
*/
|
||||
function showExpressInstall(att, par, replaceElemIdStr, callbackFn) {
|
||||
isExpressInstallActive = true;
|
||||
storedCallbackFn = callbackFn || null;
|
||||
storedCallbackObj = {success:false, id:replaceElemIdStr};
|
||||
var obj = getElementById(replaceElemIdStr);
|
||||
if (obj) {
|
||||
if (obj.nodeName == "OBJECT") { // static publishing
|
||||
storedAltContent = abstractAltContent(obj);
|
||||
storedAltContentId = null;
|
||||
}
|
||||
else { // dynamic publishing
|
||||
storedAltContent = obj;
|
||||
storedAltContentId = replaceElemIdStr;
|
||||
}
|
||||
att.id = EXPRESS_INSTALL_ID;
|
||||
if (typeof att.width == UNDEF || (!/%$/.test(att.width) && parseInt(att.width, 10) < 310)) { att.width = "310"; }
|
||||
if (typeof att.height == UNDEF || (!/%$/.test(att.height) && parseInt(att.height, 10) < 137)) { att.height = "137"; }
|
||||
doc.title = doc.title.slice(0, 47) + " - Flash Player Installation";
|
||||
var pt = ua.ie && ua.win ? "ActiveX" : "PlugIn",
|
||||
fv = "MMredirectURL=" + encodeURI(window.location).toString().replace(/&/g,"%26") + "&MMplayerType=" + pt + "&MMdoctitle=" + doc.title;
|
||||
if (typeof par.flashvars != UNDEF) {
|
||||
par.flashvars += "&" + fv;
|
||||
}
|
||||
else {
|
||||
par.flashvars = fv;
|
||||
}
|
||||
// IE only: when a SWF is loading (AND: not available in cache) wait for the readyState of the object element to become 4 before removing it,
|
||||
// because you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work
|
||||
if (ua.ie && ua.win && obj.readyState != 4) {
|
||||
var newObj = createElement("div");
|
||||
replaceElemIdStr += "SWFObjectNew";
|
||||
newObj.setAttribute("id", replaceElemIdStr);
|
||||
obj.parentNode.insertBefore(newObj, obj); // insert placeholder div that will be replaced by the object element that loads expressinstall.swf
|
||||
obj.style.display = "none";
|
||||
(function(){
|
||||
if (obj.readyState == 4) {
|
||||
obj.parentNode.removeChild(obj);
|
||||
}
|
||||
else {
|
||||
setTimeout(arguments.callee, 10);
|
||||
}
|
||||
})();
|
||||
}
|
||||
createSWF(att, par, replaceElemIdStr);
|
||||
}
|
||||
}
|
||||
|
||||
/* Functions to abstract and display alternative content
|
||||
*/
|
||||
function displayAltContent(obj) {
|
||||
if (ua.ie && ua.win && obj.readyState != 4) {
|
||||
// IE only: when a SWF is loading (AND: not available in cache) wait for the readyState of the object element to become 4 before removing it,
|
||||
// because you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work
|
||||
var el = createElement("div");
|
||||
obj.parentNode.insertBefore(el, obj); // insert placeholder div that will be replaced by the alternative content
|
||||
el.parentNode.replaceChild(abstractAltContent(obj), el);
|
||||
obj.style.display = "none";
|
||||
(function(){
|
||||
if (obj.readyState == 4) {
|
||||
obj.parentNode.removeChild(obj);
|
||||
}
|
||||
else {
|
||||
setTimeout(arguments.callee, 10);
|
||||
}
|
||||
})();
|
||||
}
|
||||
else {
|
||||
obj.parentNode.replaceChild(abstractAltContent(obj), obj);
|
||||
}
|
||||
}
|
||||
|
||||
function abstractAltContent(obj) {
|
||||
var ac = createElement("div");
|
||||
if (ua.win && ua.ie) {
|
||||
ac.innerHTML = obj.innerHTML;
|
||||
}
|
||||
else {
|
||||
var nestedObj = obj.getElementsByTagName(OBJECT)[0];
|
||||
if (nestedObj) {
|
||||
var c = nestedObj.childNodes;
|
||||
if (c) {
|
||||
var cl = c.length;
|
||||
for (var i = 0; i < cl; i++) {
|
||||
if (!(c[i].nodeType == 1 && c[i].nodeName == "PARAM") && !(c[i].nodeType == 8)) {
|
||||
ac.appendChild(c[i].cloneNode(true));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ac;
|
||||
}
|
||||
|
||||
/* Cross-browser dynamic SWF creation
|
||||
*/
|
||||
function createSWF(attObj, parObj, id) {
|
||||
var r, el = getElementById(id);
|
||||
if (ua.wk && ua.wk < 312) { return r; }
|
||||
if (el) {
|
||||
if (typeof attObj.id == UNDEF) { // if no 'id' is defined for the object element, it will inherit the 'id' from the alternative content
|
||||
attObj.id = id;
|
||||
}
|
||||
if (ua.ie && ua.win) { // Internet Explorer + the HTML object element + W3C DOM methods do not combine: fall back to outerHTML
|
||||
var att = "";
|
||||
for (var i in attObj) {
|
||||
if (attObj[i] != Object.prototype[i]) { // filter out prototype additions from other potential libraries
|
||||
if (i.toLowerCase() == "data") {
|
||||
parObj.movie = attObj[i];
|
||||
}
|
||||
else if (i.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword
|
||||
att += ' class="' + attObj[i] + '"';
|
||||
}
|
||||
else if (i.toLowerCase() != "classid") {
|
||||
att += ' ' + i + '="' + attObj[i] + '"';
|
||||
}
|
||||
}
|
||||
}
|
||||
var par = "";
|
||||
for (var j in parObj) {
|
||||
if (parObj[j] != Object.prototype[j]) { // filter out prototype additions from other potential libraries
|
||||
par += '<param name="' + j + '" value="' + parObj[j] + '" />';
|
||||
}
|
||||
}
|
||||
el.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' + att + '>' + par + '</object>';
|
||||
objIdArr[objIdArr.length] = attObj.id; // stored to fix object 'leaks' on unload (dynamic publishing only)
|
||||
r = getElementById(attObj.id);
|
||||
}
|
||||
else { // well-behaving browsers
|
||||
var o = createElement(OBJECT);
|
||||
o.setAttribute("type", FLASH_MIME_TYPE);
|
||||
for (var m in attObj) {
|
||||
if (attObj[m] != Object.prototype[m]) { // filter out prototype additions from other potential libraries
|
||||
if (m.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword
|
||||
o.setAttribute("class", attObj[m]);
|
||||
}
|
||||
else if (m.toLowerCase() != "classid") { // filter out IE specific attribute
|
||||
o.setAttribute(m, attObj[m]);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (var n in parObj) {
|
||||
if (parObj[n] != Object.prototype[n] && n.toLowerCase() != "movie") { // filter out prototype additions from other potential libraries and IE specific param element
|
||||
createObjParam(o, n, parObj[n]);
|
||||
}
|
||||
}
|
||||
el.parentNode.replaceChild(o, el);
|
||||
r = o;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
function createObjParam(el, pName, pValue) {
|
||||
var p = createElement("param");
|
||||
p.setAttribute("name", pName);
|
||||
p.setAttribute("value", pValue);
|
||||
el.appendChild(p);
|
||||
}
|
||||
|
||||
/* Cross-browser SWF removal
|
||||
- Especially needed to safely and completely remove a SWF in Internet Explorer
|
||||
*/
|
||||
function removeSWF(id) {
|
||||
var obj = getElementById(id);
|
||||
if (obj && obj.nodeName == "OBJECT") {
|
||||
if (ua.ie && ua.win) {
|
||||
obj.style.display = "none";
|
||||
(function(){
|
||||
if (obj.readyState == 4) {
|
||||
removeObjectInIE(id);
|
||||
}
|
||||
else {
|
||||
setTimeout(arguments.callee, 10);
|
||||
}
|
||||
})();
|
||||
}
|
||||
else {
|
||||
obj.parentNode.removeChild(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function removeObjectInIE(id) {
|
||||
var obj = getElementById(id);
|
||||
if (obj) {
|
||||
for (var i in obj) {
|
||||
if (typeof obj[i] == "function") {
|
||||
obj[i] = null;
|
||||
}
|
||||
}
|
||||
obj.parentNode.removeChild(obj);
|
||||
}
|
||||
}
|
||||
|
||||
/* Functions to optimize JavaScript compression
|
||||
*/
|
||||
function getElementById(id) {
|
||||
var el = null;
|
||||
try {
|
||||
el = doc.getElementById(id);
|
||||
}
|
||||
catch (e) {}
|
||||
return el;
|
||||
}
|
||||
|
||||
function createElement(el) {
|
||||
return doc.createElement(el);
|
||||
}
|
||||
|
||||
/* Updated attachEvent function for Internet Explorer
|
||||
- Stores attachEvent information in an Array, so on unload the detachEvent functions can be called to avoid memory leaks
|
||||
*/
|
||||
function addListener(target, eventType, fn) {
|
||||
target.attachEvent(eventType, fn);
|
||||
listenersArr[listenersArr.length] = [target, eventType, fn];
|
||||
}
|
||||
|
||||
/* Flash Player and SWF content version matching
|
||||
*/
|
||||
function hasPlayerVersion(rv) {
|
||||
var pv = ua.pv, v = rv.split(".");
|
||||
v[0] = parseInt(v[0], 10);
|
||||
v[1] = parseInt(v[1], 10) || 0; // supports short notation, e.g. "9" instead of "9.0.0"
|
||||
v[2] = parseInt(v[2], 10) || 0;
|
||||
return (pv[0] > v[0] || (pv[0] == v[0] && pv[1] > v[1]) || (pv[0] == v[0] && pv[1] == v[1] && pv[2] >= v[2])) ? true : false;
|
||||
}
|
||||
|
||||
/* Cross-browser dynamic CSS creation
|
||||
- Based on Bobby van der Sluis' solution: http://www.bobbyvandersluis.com/articles/dynamicCSS.php
|
||||
*/
|
||||
function createCSS(sel, decl, media, newStyle) {
|
||||
if (ua.ie && ua.mac) { return; }
|
||||
var h = doc.getElementsByTagName("head")[0];
|
||||
if (!h) { return; } // to also support badly authored HTML pages that lack a head element
|
||||
var m = (media && typeof media == "string") ? media : "screen";
|
||||
if (newStyle) {
|
||||
dynamicStylesheet = null;
|
||||
dynamicStylesheetMedia = null;
|
||||
}
|
||||
if (!dynamicStylesheet || dynamicStylesheetMedia != m) {
|
||||
// create dynamic stylesheet + get a global reference to it
|
||||
var s = createElement("style");
|
||||
s.setAttribute("type", "text/css");
|
||||
s.setAttribute("media", m);
|
||||
dynamicStylesheet = h.appendChild(s);
|
||||
if (ua.ie && ua.win && typeof doc.styleSheets != UNDEF && doc.styleSheets.length > 0) {
|
||||
dynamicStylesheet = doc.styleSheets[doc.styleSheets.length - 1];
|
||||
}
|
||||
dynamicStylesheetMedia = m;
|
||||
}
|
||||
// add style rule
|
||||
if (ua.ie && ua.win) {
|
||||
if (dynamicStylesheet && typeof dynamicStylesheet.addRule == OBJECT) {
|
||||
dynamicStylesheet.addRule(sel, decl);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (dynamicStylesheet && typeof doc.createTextNode != UNDEF) {
|
||||
dynamicStylesheet.appendChild(doc.createTextNode(sel + " {" + decl + "}"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setVisibility(id, isVisible) {
|
||||
if (!autoHideShow) { return; }
|
||||
var v = isVisible ? "visible" : "hidden";
|
||||
if (isDomLoaded && getElementById(id)) {
|
||||
getElementById(id).style.visibility = v;
|
||||
}
|
||||
else {
|
||||
createCSS("#" + id, "visibility:" + v);
|
||||
}
|
||||
}
|
||||
|
||||
/* Filter to avoid XSS attacks
|
||||
*/
|
||||
function urlEncodeIfNecessary(s) {
|
||||
var regex = /[\\\"<>\.;]/;
|
||||
var hasBadChars = regex.exec(s) != null;
|
||||
return hasBadChars && typeof encodeURIComponent != UNDEF ? encodeURIComponent(s) : s;
|
||||
}
|
||||
|
||||
/* Release memory to avoid memory leaks caused by closures, fix hanging audio/video threads and force open sockets/NetConnections to disconnect (Internet Explorer only)
|
||||
*/
|
||||
var cleanup = function() {
|
||||
if (ua.ie && ua.win) {
|
||||
window.attachEvent("onunload", function() {
|
||||
// remove listeners to avoid memory leaks
|
||||
var ll = listenersArr.length;
|
||||
for (var i = 0; i < ll; i++) {
|
||||
listenersArr[i][0].detachEvent(listenersArr[i][1], listenersArr[i][2]);
|
||||
}
|
||||
// cleanup dynamically embedded objects to fix audio/video threads and force open sockets and NetConnections to disconnect
|
||||
var il = objIdArr.length;
|
||||
for (var j = 0; j < il; j++) {
|
||||
removeSWF(objIdArr[j]);
|
||||
}
|
||||
// cleanup library's main closures to avoid memory leaks
|
||||
for (var k in ua) {
|
||||
ua[k] = null;
|
||||
}
|
||||
ua = null;
|
||||
for (var l in swfobject) {
|
||||
swfobject[l] = null;
|
||||
}
|
||||
swfobject = null;
|
||||
});
|
||||
}
|
||||
}();
|
||||
|
||||
return {
|
||||
/* Public API
|
||||
- Reference: http://code.google.com/p/swfobject/wiki/documentation
|
||||
*/
|
||||
registerObject: function(objectIdStr, swfVersionStr, xiSwfUrlStr, callbackFn) {
|
||||
if (ua.w3 && objectIdStr && swfVersionStr) {
|
||||
var regObj = {};
|
||||
regObj.id = objectIdStr;
|
||||
regObj.swfVersion = swfVersionStr;
|
||||
regObj.expressInstall = xiSwfUrlStr;
|
||||
regObj.callbackFn = callbackFn;
|
||||
regObjArr[regObjArr.length] = regObj;
|
||||
setVisibility(objectIdStr, false);
|
||||
}
|
||||
else if (callbackFn) {
|
||||
callbackFn({success:false, id:objectIdStr});
|
||||
}
|
||||
},
|
||||
|
||||
getObjectById: function(objectIdStr) {
|
||||
if (ua.w3) {
|
||||
return getObjectById(objectIdStr);
|
||||
}
|
||||
},
|
||||
|
||||
embedSWF: function(swfUrlStr, replaceElemIdStr, widthStr, heightStr, swfVersionStr, xiSwfUrlStr, flashvarsObj, parObj, attObj, callbackFn) {
|
||||
var callbackObj = {success:false, id:replaceElemIdStr};
|
||||
if (ua.w3 && !(ua.wk && ua.wk < 312) && swfUrlStr && replaceElemIdStr && widthStr && heightStr && swfVersionStr) {
|
||||
setVisibility(replaceElemIdStr, false);
|
||||
addDomLoadEvent(function() {
|
||||
widthStr += ""; // auto-convert to string
|
||||
heightStr += "";
|
||||
var att = {};
|
||||
if (attObj && typeof attObj === OBJECT) {
|
||||
for (var i in attObj) { // copy object to avoid the use of references, because web authors often reuse attObj for multiple SWFs
|
||||
att[i] = attObj[i];
|
||||
}
|
||||
}
|
||||
att.data = swfUrlStr;
|
||||
att.width = widthStr;
|
||||
att.height = heightStr;
|
||||
var par = {};
|
||||
if (parObj && typeof parObj === OBJECT) {
|
||||
for (var j in parObj) { // copy object to avoid the use of references, because web authors often reuse parObj for multiple SWFs
|
||||
par[j] = parObj[j];
|
||||
}
|
||||
}
|
||||
if (flashvarsObj && typeof flashvarsObj === OBJECT) {
|
||||
for (var k in flashvarsObj) { // copy object to avoid the use of references, because web authors often reuse flashvarsObj for multiple SWFs
|
||||
if (typeof par.flashvars != UNDEF) {
|
||||
par.flashvars += "&" + k + "=" + flashvarsObj[k];
|
||||
}
|
||||
else {
|
||||
par.flashvars = k + "=" + flashvarsObj[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hasPlayerVersion(swfVersionStr)) { // create SWF
|
||||
var obj = createSWF(att, par, replaceElemIdStr);
|
||||
if (att.id == replaceElemIdStr) {
|
||||
setVisibility(replaceElemIdStr, true);
|
||||
}
|
||||
callbackObj.success = true;
|
||||
callbackObj.ref = obj;
|
||||
}
|
||||
else if (xiSwfUrlStr && canExpressInstall()) { // show Adobe Express Install
|
||||
att.data = xiSwfUrlStr;
|
||||
showExpressInstall(att, par, replaceElemIdStr, callbackFn);
|
||||
return;
|
||||
}
|
||||
else { // show alternative content
|
||||
setVisibility(replaceElemIdStr, true);
|
||||
}
|
||||
if (callbackFn) { callbackFn(callbackObj); }
|
||||
});
|
||||
}
|
||||
else if (callbackFn) { callbackFn(callbackObj); }
|
||||
},
|
||||
|
||||
switchOffAutoHideShow: function() {
|
||||
autoHideShow = false;
|
||||
},
|
||||
|
||||
ua: ua,
|
||||
|
||||
getFlashPlayerVersion: function() {
|
||||
return { major:ua.pv[0], minor:ua.pv[1], release:ua.pv[2] };
|
||||
},
|
||||
|
||||
hasFlashPlayerVersion: hasPlayerVersion,
|
||||
|
||||
createSWF: function(attObj, parObj, replaceElemIdStr) {
|
||||
if (ua.w3) {
|
||||
return createSWF(attObj, parObj, replaceElemIdStr);
|
||||
}
|
||||
else {
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
|
||||
showExpressInstall: function(att, par, replaceElemIdStr, callbackFn) {
|
||||
if (ua.w3 && canExpressInstall()) {
|
||||
showExpressInstall(att, par, replaceElemIdStr, callbackFn);
|
||||
}
|
||||
},
|
||||
|
||||
removeSWF: function(objElemIdStr) {
|
||||
if (ua.w3) {
|
||||
removeSWF(objElemIdStr);
|
||||
}
|
||||
},
|
||||
|
||||
createCSS: function(selStr, declStr, mediaStr, newStyleBoolean) {
|
||||
if (ua.w3) {
|
||||
createCSS(selStr, declStr, mediaStr, newStyleBoolean);
|
||||
}
|
||||
},
|
||||
|
||||
addDomLoadEvent: addDomLoadEvent,
|
||||
|
||||
addLoadEvent: addLoadEvent,
|
||||
|
||||
getQueryParamValue: function(param) {
|
||||
var q = doc.location.search || doc.location.hash;
|
||||
if (q) {
|
||||
if (/\?/.test(q)) { q = q.split("?")[1]; } // strip question mark
|
||||
if (param == null) {
|
||||
return urlEncodeIfNecessary(q);
|
||||
}
|
||||
var pairs = q.split("&");
|
||||
for (var i = 0; i < pairs.length; i++) {
|
||||
if (pairs[i].substring(0, pairs[i].indexOf("=")) == param) {
|
||||
return urlEncodeIfNecessary(pairs[i].substring((pairs[i].indexOf("=") + 1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
return "";
|
||||
},
|
||||
|
||||
// For internal usage only
|
||||
expressInstallCallback: function() {
|
||||
if (isExpressInstallActive) {
|
||||
var obj = getElementById(EXPRESS_INSTALL_ID);
|
||||
if (obj && storedAltContent) {
|
||||
obj.parentNode.replaceChild(storedAltContent, obj);
|
||||
if (storedAltContentId) {
|
||||
setVisibility(storedAltContentId, true);
|
||||
if (ua.ie && ua.win) { storedAltContent.style.display = "block"; }
|
||||
}
|
||||
if (storedCallbackFn) { storedCallbackFn(storedCallbackObj); }
|
||||
}
|
||||
isExpressInstallActive = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}();
|
@ -1,6 +0,0 @@
|
||||
/* This CSS stylesheet defines styles used by required elements in a flex application page that supports browser history */
|
||||
|
||||
#ie_historyFrame { width: 0px; height: 0px; display:none }
|
||||
#firefox_anchorDiv { width: 0px; height: 0px; display:none }
|
||||
#safari_formDiv { width: 0px; height: 0px; display:none }
|
||||
#safari_rememberDiv { width: 0px; height: 0px; display:none }
|
@ -1,678 +0,0 @@
|
||||
BrowserHistoryUtils = {
|
||||
addEvent: function(elm, evType, fn, useCapture) {
|
||||
useCapture = useCapture || false;
|
||||
if (elm.addEventListener) {
|
||||
elm.addEventListener(evType, fn, useCapture);
|
||||
return true;
|
||||
}
|
||||
else if (elm.attachEvent) {
|
||||
var r = elm.attachEvent('on' + evType, fn);
|
||||
return r;
|
||||
}
|
||||
else {
|
||||
elm['on' + evType] = fn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BrowserHistory = (function() {
|
||||
// type of browser
|
||||
var browser = {
|
||||
ie: false,
|
||||
ie8: false,
|
||||
firefox: false,
|
||||
safari: false,
|
||||
opera: false,
|
||||
version: -1
|
||||
};
|
||||
|
||||
// Default app state URL to use when no fragment ID present
|
||||
var defaultHash = '';
|
||||
|
||||
// Last-known app state URL
|
||||
var currentHref = document.location.href;
|
||||
|
||||
// Initial URL (used only by IE)
|
||||
var initialHref = document.location.href;
|
||||
|
||||
// Initial URL (used only by IE)
|
||||
var initialHash = document.location.hash;
|
||||
|
||||
// History frame source URL prefix (used only by IE)
|
||||
var historyFrameSourcePrefix = 'history/historyFrame.html?';
|
||||
|
||||
// History maintenance (used only by Safari)
|
||||
var currentHistoryLength = -1;
|
||||
|
||||
// Flag to denote the existence of onhashchange
|
||||
var browserHasHashChange = false;
|
||||
|
||||
var historyHash = [];
|
||||
|
||||
var initialState = createState(initialHref, initialHref + '#' + initialHash, initialHash);
|
||||
|
||||
var backStack = [];
|
||||
var forwardStack = [];
|
||||
|
||||
var currentObjectId = null;
|
||||
|
||||
//UserAgent detection
|
||||
var useragent = navigator.userAgent.toLowerCase();
|
||||
|
||||
if (useragent.indexOf("opera") != -1) {
|
||||
browser.opera = true;
|
||||
} else if (useragent.indexOf("msie") != -1) {
|
||||
browser.ie = true;
|
||||
browser.version = parseFloat(useragent.substring(useragent.indexOf('msie') + 4));
|
||||
if (browser.version == 8)
|
||||
{
|
||||
browser.ie = false;
|
||||
browser.ie8 = true;
|
||||
}
|
||||
} else if (useragent.indexOf("safari") != -1) {
|
||||
browser.safari = true;
|
||||
browser.version = parseFloat(useragent.substring(useragent.indexOf('safari') + 7));
|
||||
} else if (useragent.indexOf("gecko") != -1) {
|
||||
browser.firefox = true;
|
||||
}
|
||||
|
||||
if (browser.ie == true && browser.version == 7) {
|
||||
window["_ie_firstload"] = false;
|
||||
}
|
||||
|
||||
function hashChangeHandler()
|
||||
{
|
||||
currentHref = document.location.href;
|
||||
var flexAppUrl = getHash();
|
||||
//ADR: to fix multiple
|
||||
if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) {
|
||||
var pl = getPlayers();
|
||||
for (var i = 0; i < pl.length; i++) {
|
||||
pl[i].browserURLChange(flexAppUrl);
|
||||
}
|
||||
} else {
|
||||
getPlayer().browserURLChange(flexAppUrl);
|
||||
}
|
||||
}
|
||||
|
||||
// Accessor functions for obtaining specific elements of the page.
|
||||
function getHistoryFrame()
|
||||
{
|
||||
return document.getElementById('ie_historyFrame');
|
||||
}
|
||||
|
||||
function getFormElement()
|
||||
{
|
||||
return document.getElementById('safari_formDiv');
|
||||
}
|
||||
|
||||
function getRememberElement()
|
||||
{
|
||||
return document.getElementById("safari_remember_field");
|
||||
}
|
||||
|
||||
// Get the Flash player object for performing ExternalInterface callbacks.
|
||||
// Updated for changes to SWFObject2.
|
||||
function getPlayer(id) {
|
||||
var i;
|
||||
|
||||
if (id && document.getElementById(id)) {
|
||||
var r = document.getElementById(id);
|
||||
if (typeof r.SetVariable != "undefined") {
|
||||
return r;
|
||||
}
|
||||
else {
|
||||
var o = r.getElementsByTagName("object");
|
||||
var e = r.getElementsByTagName("embed");
|
||||
for (i = 0; i < o.length; i++) {
|
||||
if (typeof o[i].browserURLChange != "undefined")
|
||||
return o[i];
|
||||
}
|
||||
for (i = 0; i < e.length; i++) {
|
||||
if (typeof e[i].browserURLChange != "undefined")
|
||||
return e[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
var o = document.getElementsByTagName("object");
|
||||
var e = document.getElementsByTagName("embed");
|
||||
for (i = 0; i < e.length; i++) {
|
||||
if (typeof e[i].browserURLChange != "undefined")
|
||||
{
|
||||
return e[i];
|
||||
}
|
||||
}
|
||||
for (i = 0; i < o.length; i++) {
|
||||
if (typeof o[i].browserURLChange != "undefined")
|
||||
{
|
||||
return o[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getPlayers() {
|
||||
var i;
|
||||
var players = [];
|
||||
if (players.length == 0) {
|
||||
var tmp = document.getElementsByTagName('object');
|
||||
for (i = 0; i < tmp.length; i++)
|
||||
{
|
||||
if (typeof tmp[i].browserURLChange != "undefined")
|
||||
players.push(tmp[i]);
|
||||
}
|
||||
}
|
||||
if (players.length == 0 || players[0].object == null) {
|
||||
var tmp = document.getElementsByTagName('embed');
|
||||
for (i = 0; i < tmp.length; i++)
|
||||
{
|
||||
if (typeof tmp[i].browserURLChange != "undefined")
|
||||
players.push(tmp[i]);
|
||||
}
|
||||
}
|
||||
return players;
|
||||
}
|
||||
|
||||
function getIframeHash() {
|
||||
var doc = getHistoryFrame().contentWindow.document;
|
||||
var hash = String(doc.location.search);
|
||||
if (hash.length == 1 && hash.charAt(0) == "?") {
|
||||
hash = "";
|
||||
}
|
||||
else if (hash.length >= 2 && hash.charAt(0) == "?") {
|
||||
hash = hash.substring(1);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
/* Get the current location hash excluding the '#' symbol. */
|
||||
function getHash() {
|
||||
// It would be nice if we could use document.location.hash here,
|
||||
// but it's faulty sometimes.
|
||||
var idx = document.location.href.indexOf('#');
|
||||
return (idx >= 0) ? document.location.href.substr(idx+1) : '';
|
||||
}
|
||||
|
||||
/* Get the current location hash excluding the '#' symbol. */
|
||||
function setHash(hash) {
|
||||
// It would be nice if we could use document.location.hash here,
|
||||
// but it's faulty sometimes.
|
||||
if (hash == '') hash = '#'
|
||||
document.location.hash = hash;
|
||||
}
|
||||
|
||||
function createState(baseUrl, newUrl, flexAppUrl) {
|
||||
return { 'baseUrl': baseUrl, 'newUrl': newUrl, 'flexAppUrl': flexAppUrl, 'title': null };
|
||||
}
|
||||
|
||||
/* Add a history entry to the browser.
|
||||
* baseUrl: the portion of the location prior to the '#'
|
||||
* newUrl: the entire new URL, including '#' and following fragment
|
||||
* flexAppUrl: the portion of the location following the '#' only
|
||||
*/
|
||||
function addHistoryEntry(baseUrl, newUrl, flexAppUrl) {
|
||||
|
||||
//delete all the history entries
|
||||
forwardStack = [];
|
||||
|
||||
if (browser.ie) {
|
||||
//Check to see if we are being asked to do a navigate for the first
|
||||
//history entry, and if so ignore, because it's coming from the creation
|
||||
//of the history iframe
|
||||
if (flexAppUrl == defaultHash && document.location.href == initialHref && window['_ie_firstload']) {
|
||||
currentHref = initialHref;
|
||||
return;
|
||||
}
|
||||
if ((!flexAppUrl || flexAppUrl == defaultHash) && window['_ie_firstload']) {
|
||||
newUrl = baseUrl + '#' + defaultHash;
|
||||
flexAppUrl = defaultHash;
|
||||
} else {
|
||||
// for IE, tell the history frame to go somewhere without a '#'
|
||||
// in order to get this entry into the browser history.
|
||||
getHistoryFrame().src = historyFrameSourcePrefix + flexAppUrl;
|
||||
}
|
||||
setHash(flexAppUrl);
|
||||
} else {
|
||||
|
||||
//ADR
|
||||
if (backStack.length == 0 && initialState.flexAppUrl == flexAppUrl) {
|
||||
initialState = createState(baseUrl, newUrl, flexAppUrl);
|
||||
} else if(backStack.length > 0 && backStack[backStack.length - 1].flexAppUrl == flexAppUrl) {
|
||||
backStack[backStack.length - 1] = createState(baseUrl, newUrl, flexAppUrl);
|
||||
}
|
||||
|
||||
if (browser.safari && !browserHasHashChange) {
|
||||
// for Safari, submit a form whose action points to the desired URL
|
||||
if (browser.version <= 419.3) {
|
||||
var file = window.location.pathname.toString();
|
||||
file = file.substring(file.lastIndexOf("/")+1);
|
||||
getFormElement().innerHTML = '<form name="historyForm" action="'+file+'#' + flexAppUrl + '" method="GET"></form>';
|
||||
//get the current elements and add them to the form
|
||||
var qs = window.location.search.substring(1);
|
||||
var qs_arr = qs.split("&");
|
||||
for (var i = 0; i < qs_arr.length; i++) {
|
||||
var tmp = qs_arr[i].split("=");
|
||||
var elem = document.createElement("input");
|
||||
elem.type = "hidden";
|
||||
elem.name = tmp[0];
|
||||
elem.value = tmp[1];
|
||||
document.forms.historyForm.appendChild(elem);
|
||||
}
|
||||
document.forms.historyForm.submit();
|
||||
} else {
|
||||
top.location.hash = flexAppUrl;
|
||||
}
|
||||
// We also have to maintain the history by hand for Safari
|
||||
historyHash[history.length] = flexAppUrl;
|
||||
_storeStates();
|
||||
} else {
|
||||
// Otherwise, just tell the browser to go there
|
||||
setHash(flexAppUrl);
|
||||
}
|
||||
}
|
||||
backStack.push(createState(baseUrl, newUrl, flexAppUrl));
|
||||
}
|
||||
|
||||
function _storeStates() {
|
||||
if (browser.safari) {
|
||||
getRememberElement().value = historyHash.join(",");
|
||||
}
|
||||
}
|
||||
|
||||
function handleBackButton() {
|
||||
//The "current" page is always at the top of the history stack.
|
||||
var current = backStack.pop();
|
||||
if (!current) { return; }
|
||||
var last = backStack[backStack.length - 1];
|
||||
if (!last && backStack.length == 0){
|
||||
last = initialState;
|
||||
}
|
||||
forwardStack.push(current);
|
||||
}
|
||||
|
||||
function handleForwardButton() {
|
||||
//summary: private method. Do not call this directly.
|
||||
|
||||
var last = forwardStack.pop();
|
||||
if (!last) { return; }
|
||||
backStack.push(last);
|
||||
}
|
||||
|
||||
function handleArbitraryUrl() {
|
||||
//delete all the history entries
|
||||
forwardStack = [];
|
||||
}
|
||||
|
||||
/* Called periodically to poll to see if we need to detect navigation that has occurred */
|
||||
function checkForUrlChange() {
|
||||
|
||||
if (browser.ie) {
|
||||
if (currentHref != document.location.href && currentHref + '#' != document.location.href) {
|
||||
//This occurs when the user has navigated to a specific URL
|
||||
//within the app, and didn't use browser back/forward
|
||||
//IE seems to have a bug where it stops updating the URL it
|
||||
//shows the end-user at this point, but programatically it
|
||||
//appears to be correct. Do a full app reload to get around
|
||||
//this issue.
|
||||
if (browser.version < 7) {
|
||||
currentHref = document.location.href;
|
||||
document.location.reload();
|
||||
} else {
|
||||
if (getHash() != getIframeHash()) {
|
||||
// this.iframe.src = this.blankURL + hash;
|
||||
var sourceToSet = historyFrameSourcePrefix + getHash();
|
||||
getHistoryFrame().src = sourceToSet;
|
||||
currentHref = document.location.href;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (browser.safari && !browserHasHashChange) {
|
||||
// For Safari, we have to check to see if history.length changed.
|
||||
if (currentHistoryLength >= 0 && history.length != currentHistoryLength) {
|
||||
//alert("did change: " + history.length + ", " + historyHash.length + "|" + historyHash[history.length] + "|>" + historyHash.join("|"));
|
||||
var flexAppUrl = getHash();
|
||||
if (browser.version < 528.16 /* Anything earlier than Safari 4.0 */)
|
||||
{
|
||||
// If it did change and we're running Safari 3.x or earlier,
|
||||
// then we have to look the old state up in our hand-maintained
|
||||
// array since document.location.hash won't have changed,
|
||||
// then call back into BrowserManager.
|
||||
currentHistoryLength = history.length;
|
||||
flexAppUrl = historyHash[currentHistoryLength];
|
||||
}
|
||||
|
||||
//ADR: to fix multiple
|
||||
if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) {
|
||||
var pl = getPlayers();
|
||||
for (var i = 0; i < pl.length; i++) {
|
||||
pl[i].browserURLChange(flexAppUrl);
|
||||
}
|
||||
} else {
|
||||
getPlayer().browserURLChange(flexAppUrl);
|
||||
}
|
||||
_storeStates();
|
||||
}
|
||||
}
|
||||
if (browser.firefox && !browserHasHashChange) {
|
||||
if (currentHref != document.location.href) {
|
||||
var bsl = backStack.length;
|
||||
|
||||
var urlActions = {
|
||||
back: false,
|
||||
forward: false,
|
||||
set: false
|
||||
}
|
||||
|
||||
if ((window.location.hash == initialHash || window.location.href == initialHref) && (bsl == 1)) {
|
||||
urlActions.back = true;
|
||||
// FIXME: could this ever be a forward button?
|
||||
// we can't clear it because we still need to check for forwards. Ugg.
|
||||
// clearInterval(this.locationTimer);
|
||||
handleBackButton();
|
||||
}
|
||||
|
||||
// first check to see if we could have gone forward. We always halt on
|
||||
// a no-hash item.
|
||||
if (forwardStack.length > 0) {
|
||||
if (forwardStack[forwardStack.length-1].flexAppUrl == getHash()) {
|
||||
urlActions.forward = true;
|
||||
handleForwardButton();
|
||||
}
|
||||
}
|
||||
|
||||
// ok, that didn't work, try someplace back in the history stack
|
||||
if ((bsl >= 2) && (backStack[bsl - 2])) {
|
||||
if (backStack[bsl - 2].flexAppUrl == getHash()) {
|
||||
urlActions.back = true;
|
||||
handleBackButton();
|
||||
}
|
||||
}
|
||||
|
||||
if (!urlActions.back && !urlActions.forward) {
|
||||
var foundInStacks = {
|
||||
back: -1,
|
||||
forward: -1
|
||||
}
|
||||
|
||||
for (var i = 0; i < backStack.length; i++) {
|
||||
if (backStack[i].flexAppUrl == getHash() && i != (bsl - 2)) {
|
||||
arbitraryUrl = true;
|
||||
foundInStacks.back = i;
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < forwardStack.length; i++) {
|
||||
if (forwardStack[i].flexAppUrl == getHash() && i != (bsl - 2)) {
|
||||
arbitraryUrl = true;
|
||||
foundInStacks.forward = i;
|
||||
}
|
||||
}
|
||||
handleArbitraryUrl();
|
||||
}
|
||||
|
||||
// Firefox changed; do a callback into BrowserManager to tell it.
|
||||
currentHref = document.location.href;
|
||||
var flexAppUrl = getHash();
|
||||
//ADR: to fix multiple
|
||||
if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) {
|
||||
var pl = getPlayers();
|
||||
for (var i = 0; i < pl.length; i++) {
|
||||
pl[i].browserURLChange(flexAppUrl);
|
||||
}
|
||||
} else {
|
||||
getPlayer().browserURLChange(flexAppUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var _initialize = function () {
|
||||
|
||||
browserHasHashChange = ("onhashchange" in document.body);
|
||||
|
||||
if (browser.ie)
|
||||
{
|
||||
var scripts = document.getElementsByTagName('script');
|
||||
for (var i = 0, s; s = scripts[i]; i++) {
|
||||
if (s.src.indexOf("history.js") > -1) {
|
||||
var iframe_location = (new String(s.src)).replace("history.js", "historyFrame.html");
|
||||
}
|
||||
}
|
||||
historyFrameSourcePrefix = iframe_location + "?";
|
||||
var src = historyFrameSourcePrefix;
|
||||
|
||||
var iframe = document.createElement("iframe");
|
||||
iframe.id = 'ie_historyFrame';
|
||||
iframe.name = 'ie_historyFrame';
|
||||
iframe.src = 'javascript:false;';
|
||||
|
||||
try {
|
||||
document.body.appendChild(iframe);
|
||||
} catch(e) {
|
||||
setTimeout(function() {
|
||||
document.body.appendChild(iframe);
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (browser.safari && !browserHasHashChange)
|
||||
{
|
||||
var rememberDiv = document.createElement("div");
|
||||
rememberDiv.id = 'safari_rememberDiv';
|
||||
document.body.appendChild(rememberDiv);
|
||||
rememberDiv.innerHTML = '<input type="text" id="safari_remember_field" style="width: 500px;">';
|
||||
|
||||
var formDiv = document.createElement("div");
|
||||
formDiv.id = 'safari_formDiv';
|
||||
document.body.appendChild(formDiv);
|
||||
|
||||
var reloader_content = document.createElement('div');
|
||||
reloader_content.id = 'safarireloader';
|
||||
var scripts = document.getElementsByTagName('script');
|
||||
for (var i = 0, s; s = scripts[i]; i++) {
|
||||
if (s.src.indexOf("history.js") > -1) {
|
||||
html = (new String(s.src)).replace(".js", ".html");
|
||||
}
|
||||
}
|
||||
reloader_content.innerHTML = '<iframe id="safarireloader-iframe" src="about:blank" frameborder="no" scrolling="no"></iframe>';
|
||||
document.body.appendChild(reloader_content);
|
||||
reloader_content.style.position = 'absolute';
|
||||
reloader_content.style.left = reloader_content.style.top = '-9999px';
|
||||
iframe = reloader_content.getElementsByTagName('iframe')[0];
|
||||
|
||||
if (document.getElementById("safari_remember_field").value != "" ) {
|
||||
historyHash = document.getElementById("safari_remember_field").value.split(",");
|
||||
}
|
||||
}
|
||||
|
||||
if (browserHasHashChange)
|
||||
document.body.onhashchange = hashChangeHandler;
|
||||
}
|
||||
|
||||
return {
|
||||
historyHash: historyHash,
|
||||
backStack: function() { return backStack; },
|
||||
forwardStack: function() { return forwardStack },
|
||||
getPlayer: getPlayer,
|
||||
initialize: function(src) {
|
||||
_initialize(src);
|
||||
},
|
||||
setURL: function(url) {
|
||||
document.location.href = url;
|
||||
},
|
||||
getURL: function() {
|
||||
return document.location.href;
|
||||
},
|
||||
getTitle: function() {
|
||||
return document.title;
|
||||
},
|
||||
setTitle: function(title) {
|
||||
try {
|
||||
backStack[backStack.length - 1].title = title;
|
||||
} catch(e) { }
|
||||
//if on safari, set the title to be the empty string.
|
||||
if (browser.safari) {
|
||||
if (title == "") {
|
||||
try {
|
||||
var tmp = window.location.href.toString();
|
||||
title = tmp.substring((tmp.lastIndexOf("/")+1), tmp.lastIndexOf("#"));
|
||||
} catch(e) {
|
||||
title = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
document.title = title;
|
||||
},
|
||||
setDefaultURL: function(def)
|
||||
{
|
||||
defaultHash = def;
|
||||
def = getHash();
|
||||
//trailing ? is important else an extra frame gets added to the history
|
||||
//when navigating back to the first page. Alternatively could check
|
||||
//in history frame navigation to compare # and ?.
|
||||
if (browser.ie)
|
||||
{
|
||||
window['_ie_firstload'] = true;
|
||||
var sourceToSet = historyFrameSourcePrefix + def;
|
||||
var func = function() {
|
||||
getHistoryFrame().src = sourceToSet;
|
||||
window.location.replace("#" + def);
|
||||
setInterval(checkForUrlChange, 50);
|
||||
}
|
||||
try {
|
||||
func();
|
||||
} catch(e) {
|
||||
window.setTimeout(function() { func(); }, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (browser.safari)
|
||||
{
|
||||
currentHistoryLength = history.length;
|
||||
if (historyHash.length == 0) {
|
||||
historyHash[currentHistoryLength] = def;
|
||||
var newloc = "#" + def;
|
||||
window.location.replace(newloc);
|
||||
} else {
|
||||
//alert(historyHash[historyHash.length-1]);
|
||||
}
|
||||
setInterval(checkForUrlChange, 50);
|
||||
}
|
||||
|
||||
|
||||
if (browser.firefox || browser.opera)
|
||||
{
|
||||
var reg = new RegExp("#" + def + "$");
|
||||
if (window.location.toString().match(reg)) {
|
||||
} else {
|
||||
var newloc ="#" + def;
|
||||
window.location.replace(newloc);
|
||||
}
|
||||
setInterval(checkForUrlChange, 50);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
/* Set the current browser URL; called from inside BrowserManager to propagate
|
||||
* the application state out to the container.
|
||||
*/
|
||||
setBrowserURL: function(flexAppUrl, objectId) {
|
||||
if (browser.ie && typeof objectId != "undefined") {
|
||||
currentObjectId = objectId;
|
||||
}
|
||||
//fromIframe = fromIframe || false;
|
||||
//fromFlex = fromFlex || false;
|
||||
//alert("setBrowserURL: " + flexAppUrl);
|
||||
//flexAppUrl = (flexAppUrl == "") ? defaultHash : flexAppUrl ;
|
||||
|
||||
var pos = document.location.href.indexOf('#');
|
||||
var baseUrl = pos != -1 ? document.location.href.substr(0, pos) : document.location.href;
|
||||
var newUrl = baseUrl + '#' + flexAppUrl;
|
||||
|
||||
if (document.location.href != newUrl && document.location.href + '#' != newUrl) {
|
||||
currentHref = newUrl;
|
||||
addHistoryEntry(baseUrl, newUrl, flexAppUrl);
|
||||
currentHistoryLength = history.length;
|
||||
}
|
||||
},
|
||||
|
||||
browserURLChange: function(flexAppUrl) {
|
||||
var objectId = null;
|
||||
if (browser.ie && currentObjectId != null) {
|
||||
objectId = currentObjectId;
|
||||
}
|
||||
|
||||
if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) {
|
||||
var pl = getPlayers();
|
||||
for (var i = 0; i < pl.length; i++) {
|
||||
try {
|
||||
pl[i].browserURLChange(flexAppUrl);
|
||||
} catch(e) { }
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
getPlayer(objectId).browserURLChange(flexAppUrl);
|
||||
} catch(e) { }
|
||||
}
|
||||
|
||||
currentObjectId = null;
|
||||
},
|
||||
getUserAgent: function() {
|
||||
return navigator.userAgent;
|
||||
},
|
||||
getPlatform: function() {
|
||||
return navigator.platform;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
// Initialization
|
||||
|
||||
// Automated unit testing and other diagnostics
|
||||
|
||||
function setURL(url)
|
||||
{
|
||||
document.location.href = url;
|
||||
}
|
||||
|
||||
function backButton()
|
||||
{
|
||||
history.back();
|
||||
}
|
||||
|
||||
function forwardButton()
|
||||
{
|
||||
history.forward();
|
||||
}
|
||||
|
||||
function goForwardOrBackInHistory(step)
|
||||
{
|
||||
history.go(step);
|
||||
}
|
||||
|
||||
//BrowserHistoryUtils.addEvent(window, "load", function() { BrowserHistory.initialize(); });
|
||||
(function(i) {
|
||||
var u =navigator.userAgent;var e=/*@cc_on!@*/false;
|
||||
var st = setTimeout;
|
||||
if(/webkit/i.test(u)){
|
||||
st(function(){
|
||||
var dr=document.readyState;
|
||||
if(dr=="loaded"||dr=="complete"){i()}
|
||||
else{st(arguments.callee,10);}},10);
|
||||
} else if((/mozilla/i.test(u)&&!/(compati)/.test(u)) || (/opera/i.test(u))){
|
||||
document.addEventListener("DOMContentLoaded",i,false);
|
||||
} else if(e){
|
||||
(function(){
|
||||
var t=document.createElement('doc:rdy');
|
||||
try{t.doScroll('left');
|
||||
i();t=null;
|
||||
}catch(e){st(arguments.callee,0);}})();
|
||||
} else{
|
||||
window.onload=i;
|
||||
}
|
||||
})( function() {BrowserHistory.initialize();} );
|
@ -1,29 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
|
||||
<META HTTP-EQUIV="Expires" CONTENT="-1">
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
function processUrl()
|
||||
{
|
||||
|
||||
var pos = url.indexOf("?");
|
||||
url = pos != -1 ? url.substr(pos + 1) : "";
|
||||
if (!parent._ie_firstload) {
|
||||
parent.BrowserHistory.setBrowserURL(url);
|
||||
try {
|
||||
parent.BrowserHistory.browserURLChange(url);
|
||||
} catch(e) { }
|
||||
} else {
|
||||
parent._ie_firstload = false;
|
||||
}
|
||||
}
|
||||
|
||||
var url = document.location.href;
|
||||
processUrl();
|
||||
document.write(encodeURIComponent(url));
|
||||
</script>
|
||||
Hidden frame for Browser History support.
|
||||
</body>
|
||||
</html>
|
@ -1,108 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<!-- saved from url=(0014)about:internet -->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
|
||||
<!--
|
||||
Smart developers always View Source.
|
||||
|
||||
This application was built using Adobe Flex, an open source framework
|
||||
for building rich Internet applications that get delivered via the
|
||||
Flash Player or to desktops via Adobe AIR.
|
||||
|
||||
Learn more about Flex at http://flex.org
|
||||
// -->
|
||||
<head>
|
||||
<title>${title}</title>
|
||||
<meta name="google" value="notranslate" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<!-- Include CSS to eliminate any default margins/padding and set the height of the html element and
|
||||
the body element to 100%, because Firefox, or any Gecko based browser, interprets percentage as
|
||||
the percentage of the height of its parent container, which has to be set explicitly. Fix for
|
||||
Firefox 3.6 focus border issues. Initially, don't display flashContent div so it won't show
|
||||
if JavaScript disabled.
|
||||
-->
|
||||
<style type="text/css" media="screen">
|
||||
html, body { height:100%; }
|
||||
body { margin:0; padding:0; overflow:auto; text-align:center;
|
||||
background-color: ${bgcolor}; }
|
||||
object:focus { outline:none; }
|
||||
#flashContent { display:none; }
|
||||
</style>
|
||||
|
||||
<!-- Enable Browser History by replacing useBrowserHistory tokens with two hyphens -->
|
||||
<!-- BEGIN Browser History required section ${useBrowserHistory}>
|
||||
<link rel="stylesheet" type="text/css" href="history/history.css" />
|
||||
<script type="text/javascript" src="history/history.js"></script>
|
||||
<!${useBrowserHistory} END Browser History required section -->
|
||||
|
||||
<script type="text/javascript" src="swfobject.js"></script>
|
||||
<script type="text/javascript">
|
||||
// For version detection, set to min. required Flash Player version, or 0 (or 0.0.0), for no version detection.
|
||||
var swfVersionStr = "${version_major}.${version_minor}.${version_revision}";
|
||||
// To use express install, set to playerProductInstall.swf, otherwise the empty string.
|
||||
var xiSwfUrlStr = "${expressInstallSwf}";
|
||||
var flashvars = {};
|
||||
var params = {};
|
||||
params.quality = "high";
|
||||
params.bgcolor = "${bgcolor}";
|
||||
params.allowscriptaccess = "sameDomain";
|
||||
params.allowfullscreen = "true";
|
||||
var attributes = {};
|
||||
attributes.id = "${application}";
|
||||
attributes.name = "${application}";
|
||||
attributes.align = "middle";
|
||||
swfobject.embedSWF(
|
||||
"${swf}.swf", "flashContent",
|
||||
"${width}", "${height}",
|
||||
swfVersionStr, xiSwfUrlStr,
|
||||
flashvars, params, attributes);
|
||||
// JavaScript enabled so display the flashContent div in case it is not replaced with a swf object.
|
||||
swfobject.createCSS("#flashContent", "display:block;text-align:left;");
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- SWFObject's dynamic embed method replaces this alternative HTML content with Flash content when enough
|
||||
JavaScript and Flash plug-in support is available. The div is initially hidden so that it doesn't show
|
||||
when JavaScript is disabled.
|
||||
-->
|
||||
<div id="flashContent">
|
||||
<p>
|
||||
To view this page ensure that Adobe Flash Player version
|
||||
${version_major}.${version_minor}.${version_revision} or greater is installed.
|
||||
</p>
|
||||
<script type="text/javascript">
|
||||
var pageHost = ((document.location.protocol == "https:") ? "https://" : "http://");
|
||||
document.write("<a href='http://www.adobe.com/go/getflashplayer'><img src='"
|
||||
+ pageHost + "www.adobe.com/images/shared/download_buttons/get_flash_player.gif' alt='Get Adobe Flash player' /></a>" );
|
||||
</script>
|
||||
</div>
|
||||
|
||||
<noscript>
|
||||
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="${width}" height="${height}" id="${application}">
|
||||
<param name="movie" value="${swf}.swf" />
|
||||
<param name="quality" value="high" />
|
||||
<param name="bgcolor" value="${bgcolor}" />
|
||||
<param name="allowScriptAccess" value="sameDomain" />
|
||||
<param name="allowFullScreen" value="true" />
|
||||
<!--[if !IE]>-->
|
||||
<object type="application/x-shockwave-flash" data="${swf}.swf" width="${width}" height="${height}">
|
||||
<param name="quality" value="high" />
|
||||
<param name="bgcolor" value="${bgcolor}" />
|
||||
<param name="allowScriptAccess" value="sameDomain" />
|
||||
<param name="allowFullScreen" value="true" />
|
||||
<!--<![endif]-->
|
||||
<!--[if gte IE 6]>-->
|
||||
<p>
|
||||
Either scripts and active content are not permitted to run or Adobe Flash Player version
|
||||
${version_major}.${version_minor}.${version_revision} or greater is not installed.
|
||||
</p>
|
||||
<!--<![endif]-->
|
||||
<a href="http://www.adobe.com/go/getflashplayer">
|
||||
<img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash Player" />
|
||||
</a>
|
||||
<!--[if !IE]>-->
|
||||
</object>
|
||||
<!--<![endif]-->
|
||||
</object>
|
||||
</noscript>
|
||||
</body>
|
||||
</html>
|
@ -1,777 +0,0 @@
|
||||
/*! SWFObject v2.2 <http://code.google.com/p/swfobject/>
|
||||
is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
|
||||
*/
|
||||
|
||||
var swfobject = function() {
|
||||
|
||||
var UNDEF = "undefined",
|
||||
OBJECT = "object",
|
||||
SHOCKWAVE_FLASH = "Shockwave Flash",
|
||||
SHOCKWAVE_FLASH_AX = "ShockwaveFlash.ShockwaveFlash",
|
||||
FLASH_MIME_TYPE = "application/x-shockwave-flash",
|
||||
EXPRESS_INSTALL_ID = "SWFObjectExprInst",
|
||||
ON_READY_STATE_CHANGE = "onreadystatechange",
|
||||
|
||||
win = window,
|
||||
doc = document,
|
||||
nav = navigator,
|
||||
|
||||
plugin = false,
|
||||
domLoadFnArr = [main],
|
||||
regObjArr = [],
|
||||
objIdArr = [],
|
||||
listenersArr = [],
|
||||
storedAltContent,
|
||||
storedAltContentId,
|
||||
storedCallbackFn,
|
||||
storedCallbackObj,
|
||||
isDomLoaded = false,
|
||||
isExpressInstallActive = false,
|
||||
dynamicStylesheet,
|
||||
dynamicStylesheetMedia,
|
||||
autoHideShow = true,
|
||||
|
||||
/* Centralized function for browser feature detection
|
||||
- User agent string detection is only used when no good alternative is possible
|
||||
- Is executed directly for optimal performance
|
||||
*/
|
||||
ua = function() {
|
||||
var w3cdom = typeof doc.getElementById != UNDEF && typeof doc.getElementsByTagName != UNDEF && typeof doc.createElement != UNDEF,
|
||||
u = nav.userAgent.toLowerCase(),
|
||||
p = nav.platform.toLowerCase(),
|
||||
windows = p ? /win/.test(p) : /win/.test(u),
|
||||
mac = p ? /mac/.test(p) : /mac/.test(u),
|
||||
webkit = /webkit/.test(u) ? parseFloat(u.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, "$1")) : false, // returns either the webkit version or false if not webkit
|
||||
ie = !+"\v1", // feature detection based on Andrea Giammarchi's solution: http://webreflection.blogspot.com/2009/01/32-bytes-to-know-if-your-browser-is-ie.html
|
||||
playerVersion = [0,0,0],
|
||||
d = null;
|
||||
if (typeof nav.plugins != UNDEF && typeof nav.plugins[SHOCKWAVE_FLASH] == OBJECT) {
|
||||
d = nav.plugins[SHOCKWAVE_FLASH].description;
|
||||
if (d && !(typeof nav.mimeTypes != UNDEF && nav.mimeTypes[FLASH_MIME_TYPE] && !nav.mimeTypes[FLASH_MIME_TYPE].enabledPlugin)) { // navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin indicates whether plug-ins are enabled or disabled in Safari 3+
|
||||
plugin = true;
|
||||
ie = false; // cascaded feature detection for Internet Explorer
|
||||
d = d.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
|
||||
playerVersion[0] = parseInt(d.replace(/^(.*)\..*$/, "$1"), 10);
|
||||
playerVersion[1] = parseInt(d.replace(/^.*\.(.*)\s.*$/, "$1"), 10);
|
||||
playerVersion[2] = /[a-zA-Z]/.test(d) ? parseInt(d.replace(/^.*[a-zA-Z]+(.*)$/, "$1"), 10) : 0;
|
||||
}
|
||||
}
|
||||
else if (typeof win.ActiveXObject != UNDEF) {
|
||||
try {
|
||||
var a = new ActiveXObject(SHOCKWAVE_FLASH_AX);
|
||||
if (a) { // a will return null when ActiveX is disabled
|
||||
d = a.GetVariable("$version");
|
||||
if (d) {
|
||||
ie = true; // cascaded feature detection for Internet Explorer
|
||||
d = d.split(" ")[1].split(",");
|
||||
playerVersion = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(e) {}
|
||||
}
|
||||
return { w3:w3cdom, pv:playerVersion, wk:webkit, ie:ie, win:windows, mac:mac };
|
||||
}(),
|
||||
|
||||
/* Cross-browser onDomLoad
|
||||
- Will fire an event as soon as the DOM of a web page is loaded
|
||||
- Internet Explorer workaround based on Diego Perini's solution: http://javascript.nwbox.com/IEContentLoaded/
|
||||
- Regular onload serves as fallback
|
||||
*/
|
||||
onDomLoad = function() {
|
||||
if (!ua.w3) { return; }
|
||||
if ((typeof doc.readyState != UNDEF && doc.readyState == "complete") || (typeof doc.readyState == UNDEF && (doc.getElementsByTagName("body")[0] || doc.body))) { // function is fired after onload, e.g. when script is inserted dynamically
|
||||
callDomLoadFunctions();
|
||||
}
|
||||
if (!isDomLoaded) {
|
||||
if (typeof doc.addEventListener != UNDEF) {
|
||||
doc.addEventListener("DOMContentLoaded", callDomLoadFunctions, false);
|
||||
}
|
||||
if (ua.ie && ua.win) {
|
||||
doc.attachEvent(ON_READY_STATE_CHANGE, function() {
|
||||
if (doc.readyState == "complete") {
|
||||
doc.detachEvent(ON_READY_STATE_CHANGE, arguments.callee);
|
||||
callDomLoadFunctions();
|
||||
}
|
||||
});
|
||||
if (win == top) { // if not inside an iframe
|
||||
(function(){
|
||||
if (isDomLoaded) { return; }
|
||||
try {
|
||||
doc.documentElement.doScroll("left");
|
||||
}
|
||||
catch(e) {
|
||||
setTimeout(arguments.callee, 0);
|
||||
return;
|
||||
}
|
||||
callDomLoadFunctions();
|
||||
})();
|
||||
}
|
||||
}
|
||||
if (ua.wk) {
|
||||
(function(){
|
||||
if (isDomLoaded) { return; }
|
||||
if (!/loaded|complete/.test(doc.readyState)) {
|
||||
setTimeout(arguments.callee, 0);
|
||||
return;
|
||||
}
|
||||
callDomLoadFunctions();
|
||||
})();
|
||||
}
|
||||
addLoadEvent(callDomLoadFunctions);
|
||||
}
|
||||
}();
|
||||
|
||||
function callDomLoadFunctions() {
|
||||
if (isDomLoaded) { return; }
|
||||
try { // test if we can really add/remove elements to/from the DOM; we don't want to fire it too early
|
||||
var t = doc.getElementsByTagName("body")[0].appendChild(createElement("span"));
|
||||
t.parentNode.removeChild(t);
|
||||
}
|
||||
catch (e) { return; }
|
||||
isDomLoaded = true;
|
||||
var dl = domLoadFnArr.length;
|
||||
for (var i = 0; i < dl; i++) {
|
||||
domLoadFnArr[i]();
|
||||
}
|
||||
}
|
||||
|
||||
function addDomLoadEvent(fn) {
|
||||
if (isDomLoaded) {
|
||||
fn();
|
||||
}
|
||||
else {
|
||||
domLoadFnArr[domLoadFnArr.length] = fn; // Array.push() is only available in IE5.5+
|
||||
}
|
||||
}
|
||||
|
||||
/* Cross-browser onload
|
||||
- Based on James Edwards' solution: http://brothercake.com/site/resources/scripts/onload/
|
||||
- Will fire an event as soon as a web page including all of its assets are loaded
|
||||
*/
|
||||
function addLoadEvent(fn) {
|
||||
if (typeof win.addEventListener != UNDEF) {
|
||||
win.addEventListener("load", fn, false);
|
||||
}
|
||||
else if (typeof doc.addEventListener != UNDEF) {
|
||||
doc.addEventListener("load", fn, false);
|
||||
}
|
||||
else if (typeof win.attachEvent != UNDEF) {
|
||||
addListener(win, "onload", fn);
|
||||
}
|
||||
else if (typeof win.onload == "function") {
|
||||
var fnOld = win.onload;
|
||||
win.onload = function() {
|
||||
fnOld();
|
||||
fn();
|
||||
};
|
||||
}
|
||||
else {
|
||||
win.onload = fn;
|
||||
}
|
||||
}
|
||||
|
||||
/* Main function
|
||||
- Will preferably execute onDomLoad, otherwise onload (as a fallback)
|
||||
*/
|
||||
function main() {
|
||||
if (plugin) {
|
||||
testPlayerVersion();
|
||||
}
|
||||
else {
|
||||
matchVersions();
|
||||
}
|
||||
}
|
||||
|
||||
/* Detect the Flash Player version for non-Internet Explorer browsers
|
||||
- Detecting the plug-in version via the object element is more precise than using the plugins collection item's description:
|
||||
a. Both release and build numbers can be detected
|
||||
b. Avoid wrong descriptions by corrupt installers provided by Adobe
|
||||
c. Avoid wrong descriptions by multiple Flash Player entries in the plugin Array, caused by incorrect browser imports
|
||||
- Disadvantage of this method is that it depends on the availability of the DOM, while the plugins collection is immediately available
|
||||
*/
|
||||
function testPlayerVersion() {
|
||||
var b = doc.getElementsByTagName("body")[0];
|
||||
var o = createElement(OBJECT);
|
||||
o.setAttribute("type", FLASH_MIME_TYPE);
|
||||
var t = b.appendChild(o);
|
||||
if (t) {
|
||||
var counter = 0;
|
||||
(function(){
|
||||
if (typeof t.GetVariable != UNDEF) {
|
||||
var d = t.GetVariable("$version");
|
||||
if (d) {
|
||||
d = d.split(" ")[1].split(",");
|
||||
ua.pv = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
|
||||
}
|
||||
}
|
||||
else if (counter < 10) {
|
||||
counter++;
|
||||
setTimeout(arguments.callee, 10);
|
||||
return;
|
||||
}
|
||||
b.removeChild(o);
|
||||
t = null;
|
||||
matchVersions();
|
||||
})();
|
||||
}
|
||||
else {
|
||||
matchVersions();
|
||||
}
|
||||
}
|
||||
|
||||
/* Perform Flash Player and SWF version matching; static publishing only
|
||||
*/
|
||||
function matchVersions() {
|
||||
var rl = regObjArr.length;
|
||||
if (rl > 0) {
|
||||
for (var i = 0; i < rl; i++) { // for each registered object element
|
||||
var id = regObjArr[i].id;
|
||||
var cb = regObjArr[i].callbackFn;
|
||||
var cbObj = {success:false, id:id};
|
||||
if (ua.pv[0] > 0) {
|
||||
var obj = getElementById(id);
|
||||
if (obj) {
|
||||
if (hasPlayerVersion(regObjArr[i].swfVersion) && !(ua.wk && ua.wk < 312)) { // Flash Player version >= published SWF version: Houston, we have a match!
|
||||
setVisibility(id, true);
|
||||
if (cb) {
|
||||
cbObj.success = true;
|
||||
cbObj.ref = getObjectById(id);
|
||||
cb(cbObj);
|
||||
}
|
||||
}
|
||||
else if (regObjArr[i].expressInstall && canExpressInstall()) { // show the Adobe Express Install dialog if set by the web page author and if supported
|
||||
var att = {};
|
||||
att.data = regObjArr[i].expressInstall;
|
||||
att.width = obj.getAttribute("width") || "0";
|
||||
att.height = obj.getAttribute("height") || "0";
|
||||
if (obj.getAttribute("class")) { att.styleclass = obj.getAttribute("class"); }
|
||||
if (obj.getAttribute("align")) { att.align = obj.getAttribute("align"); }
|
||||
// parse HTML object param element's name-value pairs
|
||||
var par = {};
|
||||
var p = obj.getElementsByTagName("param");
|
||||
var pl = p.length;
|
||||
for (var j = 0; j < pl; j++) {
|
||||
if (p[j].getAttribute("name").toLowerCase() != "movie") {
|
||||
par[p[j].getAttribute("name")] = p[j].getAttribute("value");
|
||||
}
|
||||
}
|
||||
showExpressInstall(att, par, id, cb);
|
||||
}
|
||||
else { // Flash Player and SWF version mismatch or an older Webkit engine that ignores the HTML object element's nested param elements: display alternative content instead of SWF
|
||||
displayAltContent(obj);
|
||||
if (cb) { cb(cbObj); }
|
||||
}
|
||||
}
|
||||
}
|
||||
else { // if no Flash Player is installed or the fp version cannot be detected we let the HTML object element do its job (either show a SWF or alternative content)
|
||||
setVisibility(id, true);
|
||||
if (cb) {
|
||||
var o = getObjectById(id); // test whether there is an HTML object element or not
|
||||
if (o && typeof o.SetVariable != UNDEF) {
|
||||
cbObj.success = true;
|
||||
cbObj.ref = o;
|
||||
}
|
||||
cb(cbObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getObjectById(objectIdStr) {
|
||||
var r = null;
|
||||
var o = getElementById(objectIdStr);
|
||||
if (o && o.nodeName == "OBJECT") {
|
||||
if (typeof o.SetVariable != UNDEF) {
|
||||
r = o;
|
||||
}
|
||||
else {
|
||||
var n = o.getElementsByTagName(OBJECT)[0];
|
||||
if (n) {
|
||||
r = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Requirements for Adobe Express Install
|
||||
- only one instance can be active at a time
|
||||
- fp 6.0.65 or higher
|
||||
- Win/Mac OS only
|
||||
- no Webkit engines older than version 312
|
||||
*/
|
||||
function canExpressInstall() {
|
||||
return !isExpressInstallActive && hasPlayerVersion("6.0.65") && (ua.win || ua.mac) && !(ua.wk && ua.wk < 312);
|
||||
}
|
||||
|
||||
/* Show the Adobe Express Install dialog
|
||||
- Reference: http://www.adobe.com/cfusion/knowledgebase/index.cfm?id=6a253b75
|
||||
*/
|
||||
function showExpressInstall(att, par, replaceElemIdStr, callbackFn) {
|
||||
isExpressInstallActive = true;
|
||||
storedCallbackFn = callbackFn || null;
|
||||
storedCallbackObj = {success:false, id:replaceElemIdStr};
|
||||
var obj = getElementById(replaceElemIdStr);
|
||||
if (obj) {
|
||||
if (obj.nodeName == "OBJECT") { // static publishing
|
||||
storedAltContent = abstractAltContent(obj);
|
||||
storedAltContentId = null;
|
||||
}
|
||||
else { // dynamic publishing
|
||||
storedAltContent = obj;
|
||||
storedAltContentId = replaceElemIdStr;
|
||||
}
|
||||
att.id = EXPRESS_INSTALL_ID;
|
||||
if (typeof att.width == UNDEF || (!/%$/.test(att.width) && parseInt(att.width, 10) < 310)) { att.width = "310"; }
|
||||
if (typeof att.height == UNDEF || (!/%$/.test(att.height) && parseInt(att.height, 10) < 137)) { att.height = "137"; }
|
||||
doc.title = doc.title.slice(0, 47) + " - Flash Player Installation";
|
||||
var pt = ua.ie && ua.win ? "ActiveX" : "PlugIn",
|
||||
fv = "MMredirectURL=" + encodeURI(window.location).toString().replace(/&/g,"%26") + "&MMplayerType=" + pt + "&MMdoctitle=" + doc.title;
|
||||
if (typeof par.flashvars != UNDEF) {
|
||||
par.flashvars += "&" + fv;
|
||||
}
|
||||
else {
|
||||
par.flashvars = fv;
|
||||
}
|
||||
// IE only: when a SWF is loading (AND: not available in cache) wait for the readyState of the object element to become 4 before removing it,
|
||||
// because you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work
|
||||
if (ua.ie && ua.win && obj.readyState != 4) {
|
||||
var newObj = createElement("div");
|
||||
replaceElemIdStr += "SWFObjectNew";
|
||||
newObj.setAttribute("id", replaceElemIdStr);
|
||||
obj.parentNode.insertBefore(newObj, obj); // insert placeholder div that will be replaced by the object element that loads expressinstall.swf
|
||||
obj.style.display = "none";
|
||||
(function(){
|
||||
if (obj.readyState == 4) {
|
||||
obj.parentNode.removeChild(obj);
|
||||
}
|
||||
else {
|
||||
setTimeout(arguments.callee, 10);
|
||||
}
|
||||
})();
|
||||
}
|
||||
createSWF(att, par, replaceElemIdStr);
|
||||
}
|
||||
}
|
||||
|
||||
/* Functions to abstract and display alternative content
|
||||
*/
|
||||
function displayAltContent(obj) {
|
||||
if (ua.ie && ua.win && obj.readyState != 4) {
|
||||
// IE only: when a SWF is loading (AND: not available in cache) wait for the readyState of the object element to become 4 before removing it,
|
||||
// because you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work
|
||||
var el = createElement("div");
|
||||
obj.parentNode.insertBefore(el, obj); // insert placeholder div that will be replaced by the alternative content
|
||||
el.parentNode.replaceChild(abstractAltContent(obj), el);
|
||||
obj.style.display = "none";
|
||||
(function(){
|
||||
if (obj.readyState == 4) {
|
||||
obj.parentNode.removeChild(obj);
|
||||
}
|
||||
else {
|
||||
setTimeout(arguments.callee, 10);
|
||||
}
|
||||
})();
|
||||
}
|
||||
else {
|
||||
obj.parentNode.replaceChild(abstractAltContent(obj), obj);
|
||||
}
|
||||
}
|
||||
|
||||
function abstractAltContent(obj) {
|
||||
var ac = createElement("div");
|
||||
if (ua.win && ua.ie) {
|
||||
ac.innerHTML = obj.innerHTML;
|
||||
}
|
||||
else {
|
||||
var nestedObj = obj.getElementsByTagName(OBJECT)[0];
|
||||
if (nestedObj) {
|
||||
var c = nestedObj.childNodes;
|
||||
if (c) {
|
||||
var cl = c.length;
|
||||
for (var i = 0; i < cl; i++) {
|
||||
if (!(c[i].nodeType == 1 && c[i].nodeName == "PARAM") && !(c[i].nodeType == 8)) {
|
||||
ac.appendChild(c[i].cloneNode(true));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ac;
|
||||
}
|
||||
|
||||
/* Cross-browser dynamic SWF creation
|
||||
*/
|
||||
function createSWF(attObj, parObj, id) {
|
||||
var r, el = getElementById(id);
|
||||
if (ua.wk && ua.wk < 312) { return r; }
|
||||
if (el) {
|
||||
if (typeof attObj.id == UNDEF) { // if no 'id' is defined for the object element, it will inherit the 'id' from the alternative content
|
||||
attObj.id = id;
|
||||
}
|
||||
if (ua.ie && ua.win) { // Internet Explorer + the HTML object element + W3C DOM methods do not combine: fall back to outerHTML
|
||||
var att = "";
|
||||
for (var i in attObj) {
|
||||
if (attObj[i] != Object.prototype[i]) { // filter out prototype additions from other potential libraries
|
||||
if (i.toLowerCase() == "data") {
|
||||
parObj.movie = attObj[i];
|
||||
}
|
||||
else if (i.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword
|
||||
att += ' class="' + attObj[i] + '"';
|
||||
}
|
||||
else if (i.toLowerCase() != "classid") {
|
||||
att += ' ' + i + '="' + attObj[i] + '"';
|
||||
}
|
||||
}
|
||||
}
|
||||
var par = "";
|
||||
for (var j in parObj) {
|
||||
if (parObj[j] != Object.prototype[j]) { // filter out prototype additions from other potential libraries
|
||||
par += '<param name="' + j + '" value="' + parObj[j] + '" />';
|
||||
}
|
||||
}
|
||||
el.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' + att + '>' + par + '</object>';
|
||||
objIdArr[objIdArr.length] = attObj.id; // stored to fix object 'leaks' on unload (dynamic publishing only)
|
||||
r = getElementById(attObj.id);
|
||||
}
|
||||
else { // well-behaving browsers
|
||||
var o = createElement(OBJECT);
|
||||
o.setAttribute("type", FLASH_MIME_TYPE);
|
||||
for (var m in attObj) {
|
||||
if (attObj[m] != Object.prototype[m]) { // filter out prototype additions from other potential libraries
|
||||
if (m.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword
|
||||
o.setAttribute("class", attObj[m]);
|
||||
}
|
||||
else if (m.toLowerCase() != "classid") { // filter out IE specific attribute
|
||||
o.setAttribute(m, attObj[m]);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (var n in parObj) {
|
||||
if (parObj[n] != Object.prototype[n] && n.toLowerCase() != "movie") { // filter out prototype additions from other potential libraries and IE specific param element
|
||||
createObjParam(o, n, parObj[n]);
|
||||
}
|
||||
}
|
||||
el.parentNode.replaceChild(o, el);
|
||||
r = o;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
function createObjParam(el, pName, pValue) {
|
||||
var p = createElement("param");
|
||||
p.setAttribute("name", pName);
|
||||
p.setAttribute("value", pValue);
|
||||
el.appendChild(p);
|
||||
}
|
||||
|
||||
/* Cross-browser SWF removal
|
||||
- Especially needed to safely and completely remove a SWF in Internet Explorer
|
||||
*/
|
||||
function removeSWF(id) {
|
||||
var obj = getElementById(id);
|
||||
if (obj && obj.nodeName == "OBJECT") {
|
||||
if (ua.ie && ua.win) {
|
||||
obj.style.display = "none";
|
||||
(function(){
|
||||
if (obj.readyState == 4) {
|
||||
removeObjectInIE(id);
|
||||
}
|
||||
else {
|
||||
setTimeout(arguments.callee, 10);
|
||||
}
|
||||
})();
|
||||
}
|
||||
else {
|
||||
obj.parentNode.removeChild(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function removeObjectInIE(id) {
|
||||
var obj = getElementById(id);
|
||||
if (obj) {
|
||||
for (var i in obj) {
|
||||
if (typeof obj[i] == "function") {
|
||||
obj[i] = null;
|
||||
}
|
||||
}
|
||||
obj.parentNode.removeChild(obj);
|
||||
}
|
||||
}
|
||||
|
||||
/* Functions to optimize JavaScript compression
|
||||
*/
|
||||
function getElementById(id) {
|
||||
var el = null;
|
||||
try {
|
||||
el = doc.getElementById(id);
|
||||
}
|
||||
catch (e) {}
|
||||
return el;
|
||||
}
|
||||
|
||||
function createElement(el) {
|
||||
return doc.createElement(el);
|
||||
}
|
||||
|
||||
/* Updated attachEvent function for Internet Explorer
|
||||
- Stores attachEvent information in an Array, so on unload the detachEvent functions can be called to avoid memory leaks
|
||||
*/
|
||||
function addListener(target, eventType, fn) {
|
||||
target.attachEvent(eventType, fn);
|
||||
listenersArr[listenersArr.length] = [target, eventType, fn];
|
||||
}
|
||||
|
||||
/* Flash Player and SWF content version matching
|
||||
*/
|
||||
function hasPlayerVersion(rv) {
|
||||
var pv = ua.pv, v = rv.split(".");
|
||||
v[0] = parseInt(v[0], 10);
|
||||
v[1] = parseInt(v[1], 10) || 0; // supports short notation, e.g. "9" instead of "9.0.0"
|
||||
v[2] = parseInt(v[2], 10) || 0;
|
||||
return (pv[0] > v[0] || (pv[0] == v[0] && pv[1] > v[1]) || (pv[0] == v[0] && pv[1] == v[1] && pv[2] >= v[2])) ? true : false;
|
||||
}
|
||||
|
||||
/* Cross-browser dynamic CSS creation
|
||||
- Based on Bobby van der Sluis' solution: http://www.bobbyvandersluis.com/articles/dynamicCSS.php
|
||||
*/
|
||||
function createCSS(sel, decl, media, newStyle) {
|
||||
if (ua.ie && ua.mac) { return; }
|
||||
var h = doc.getElementsByTagName("head")[0];
|
||||
if (!h) { return; } // to also support badly authored HTML pages that lack a head element
|
||||
var m = (media && typeof media == "string") ? media : "screen";
|
||||
if (newStyle) {
|
||||
dynamicStylesheet = null;
|
||||
dynamicStylesheetMedia = null;
|
||||
}
|
||||
if (!dynamicStylesheet || dynamicStylesheetMedia != m) {
|
||||
// create dynamic stylesheet + get a global reference to it
|
||||
var s = createElement("style");
|
||||
s.setAttribute("type", "text/css");
|
||||
s.setAttribute("media", m);
|
||||
dynamicStylesheet = h.appendChild(s);
|
||||
if (ua.ie && ua.win && typeof doc.styleSheets != UNDEF && doc.styleSheets.length > 0) {
|
||||
dynamicStylesheet = doc.styleSheets[doc.styleSheets.length - 1];
|
||||
}
|
||||
dynamicStylesheetMedia = m;
|
||||
}
|
||||
// add style rule
|
||||
if (ua.ie && ua.win) {
|
||||
if (dynamicStylesheet && typeof dynamicStylesheet.addRule == OBJECT) {
|
||||
dynamicStylesheet.addRule(sel, decl);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (dynamicStylesheet && typeof doc.createTextNode != UNDEF) {
|
||||
dynamicStylesheet.appendChild(doc.createTextNode(sel + " {" + decl + "}"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setVisibility(id, isVisible) {
|
||||
if (!autoHideShow) { return; }
|
||||
var v = isVisible ? "visible" : "hidden";
|
||||
if (isDomLoaded && getElementById(id)) {
|
||||
getElementById(id).style.visibility = v;
|
||||
}
|
||||
else {
|
||||
createCSS("#" + id, "visibility:" + v);
|
||||
}
|
||||
}
|
||||
|
||||
/* Filter to avoid XSS attacks
|
||||
*/
|
||||
function urlEncodeIfNecessary(s) {
|
||||
var regex = /[\\\"<>\.;]/;
|
||||
var hasBadChars = regex.exec(s) != null;
|
||||
return hasBadChars && typeof encodeURIComponent != UNDEF ? encodeURIComponent(s) : s;
|
||||
}
|
||||
|
||||
/* Release memory to avoid memory leaks caused by closures, fix hanging audio/video threads and force open sockets/NetConnections to disconnect (Internet Explorer only)
|
||||
*/
|
||||
var cleanup = function() {
|
||||
if (ua.ie && ua.win) {
|
||||
window.attachEvent("onunload", function() {
|
||||
// remove listeners to avoid memory leaks
|
||||
var ll = listenersArr.length;
|
||||
for (var i = 0; i < ll; i++) {
|
||||
listenersArr[i][0].detachEvent(listenersArr[i][1], listenersArr[i][2]);
|
||||
}
|
||||
// cleanup dynamically embedded objects to fix audio/video threads and force open sockets and NetConnections to disconnect
|
||||
var il = objIdArr.length;
|
||||
for (var j = 0; j < il; j++) {
|
||||
removeSWF(objIdArr[j]);
|
||||
}
|
||||
// cleanup library's main closures to avoid memory leaks
|
||||
for (var k in ua) {
|
||||
ua[k] = null;
|
||||
}
|
||||
ua = null;
|
||||
for (var l in swfobject) {
|
||||
swfobject[l] = null;
|
||||
}
|
||||
swfobject = null;
|
||||
});
|
||||
}
|
||||
}();
|
||||
|
||||
return {
|
||||
/* Public API
|
||||
- Reference: http://code.google.com/p/swfobject/wiki/documentation
|
||||
*/
|
||||
registerObject: function(objectIdStr, swfVersionStr, xiSwfUrlStr, callbackFn) {
|
||||
if (ua.w3 && objectIdStr && swfVersionStr) {
|
||||
var regObj = {};
|
||||
regObj.id = objectIdStr;
|
||||
regObj.swfVersion = swfVersionStr;
|
||||
regObj.expressInstall = xiSwfUrlStr;
|
||||
regObj.callbackFn = callbackFn;
|
||||
regObjArr[regObjArr.length] = regObj;
|
||||
setVisibility(objectIdStr, false);
|
||||
}
|
||||
else if (callbackFn) {
|
||||
callbackFn({success:false, id:objectIdStr});
|
||||
}
|
||||
},
|
||||
|
||||
getObjectById: function(objectIdStr) {
|
||||
if (ua.w3) {
|
||||
return getObjectById(objectIdStr);
|
||||
}
|
||||
},
|
||||
|
||||
embedSWF: function(swfUrlStr, replaceElemIdStr, widthStr, heightStr, swfVersionStr, xiSwfUrlStr, flashvarsObj, parObj, attObj, callbackFn) {
|
||||
var callbackObj = {success:false, id:replaceElemIdStr};
|
||||
if (ua.w3 && !(ua.wk && ua.wk < 312) && swfUrlStr && replaceElemIdStr && widthStr && heightStr && swfVersionStr) {
|
||||
setVisibility(replaceElemIdStr, false);
|
||||
addDomLoadEvent(function() {
|
||||
widthStr += ""; // auto-convert to string
|
||||
heightStr += "";
|
||||
var att = {};
|
||||
if (attObj && typeof attObj === OBJECT) {
|
||||
for (var i in attObj) { // copy object to avoid the use of references, because web authors often reuse attObj for multiple SWFs
|
||||
att[i] = attObj[i];
|
||||
}
|
||||
}
|
||||
att.data = swfUrlStr;
|
||||
att.width = widthStr;
|
||||
att.height = heightStr;
|
||||
var par = {};
|
||||
if (parObj && typeof parObj === OBJECT) {
|
||||
for (var j in parObj) { // copy object to avoid the use of references, because web authors often reuse parObj for multiple SWFs
|
||||
par[j] = parObj[j];
|
||||
}
|
||||
}
|
||||
if (flashvarsObj && typeof flashvarsObj === OBJECT) {
|
||||
for (var k in flashvarsObj) { // copy object to avoid the use of references, because web authors often reuse flashvarsObj for multiple SWFs
|
||||
if (typeof par.flashvars != UNDEF) {
|
||||
par.flashvars += "&" + k + "=" + flashvarsObj[k];
|
||||
}
|
||||
else {
|
||||
par.flashvars = k + "=" + flashvarsObj[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hasPlayerVersion(swfVersionStr)) { // create SWF
|
||||
var obj = createSWF(att, par, replaceElemIdStr);
|
||||
if (att.id == replaceElemIdStr) {
|
||||
setVisibility(replaceElemIdStr, true);
|
||||
}
|
||||
callbackObj.success = true;
|
||||
callbackObj.ref = obj;
|
||||
}
|
||||
else if (xiSwfUrlStr && canExpressInstall()) { // show Adobe Express Install
|
||||
att.data = xiSwfUrlStr;
|
||||
showExpressInstall(att, par, replaceElemIdStr, callbackFn);
|
||||
return;
|
||||
}
|
||||
else { // show alternative content
|
||||
setVisibility(replaceElemIdStr, true);
|
||||
}
|
||||
if (callbackFn) { callbackFn(callbackObj); }
|
||||
});
|
||||
}
|
||||
else if (callbackFn) { callbackFn(callbackObj); }
|
||||
},
|
||||
|
||||
switchOffAutoHideShow: function() {
|
||||
autoHideShow = false;
|
||||
},
|
||||
|
||||
ua: ua,
|
||||
|
||||
getFlashPlayerVersion: function() {
|
||||
return { major:ua.pv[0], minor:ua.pv[1], release:ua.pv[2] };
|
||||
},
|
||||
|
||||
hasFlashPlayerVersion: hasPlayerVersion,
|
||||
|
||||
createSWF: function(attObj, parObj, replaceElemIdStr) {
|
||||
if (ua.w3) {
|
||||
return createSWF(attObj, parObj, replaceElemIdStr);
|
||||
}
|
||||
else {
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
|
||||
showExpressInstall: function(att, par, replaceElemIdStr, callbackFn) {
|
||||
if (ua.w3 && canExpressInstall()) {
|
||||
showExpressInstall(att, par, replaceElemIdStr, callbackFn);
|
||||
}
|
||||
},
|
||||
|
||||
removeSWF: function(objElemIdStr) {
|
||||
if (ua.w3) {
|
||||
removeSWF(objElemIdStr);
|
||||
}
|
||||
},
|
||||
|
||||
createCSS: function(selStr, declStr, mediaStr, newStyleBoolean) {
|
||||
if (ua.w3) {
|
||||
createCSS(selStr, declStr, mediaStr, newStyleBoolean);
|
||||
}
|
||||
},
|
||||
|
||||
addDomLoadEvent: addDomLoadEvent,
|
||||
|
||||
addLoadEvent: addLoadEvent,
|
||||
|
||||
getQueryParamValue: function(param) {
|
||||
var q = doc.location.search || doc.location.hash;
|
||||
if (q) {
|
||||
if (/\?/.test(q)) { q = q.split("?")[1]; } // strip question mark
|
||||
if (param == null) {
|
||||
return urlEncodeIfNecessary(q);
|
||||
}
|
||||
var pairs = q.split("&");
|
||||
for (var i = 0; i < pairs.length; i++) {
|
||||
if (pairs[i].substring(0, pairs[i].indexOf("=")) == param) {
|
||||
return urlEncodeIfNecessary(pairs[i].substring((pairs[i].indexOf("=") + 1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
return "";
|
||||
},
|
||||
|
||||
// For internal usage only
|
||||
expressInstallCallback: function() {
|
||||
if (isExpressInstallActive) {
|
||||
var obj = getElementById(EXPRESS_INSTALL_ID);
|
||||
if (obj && storedAltContent) {
|
||||
obj.parentNode.replaceChild(storedAltContent, obj);
|
||||
if (storedAltContentId) {
|
||||
setVisibility(storedAltContentId, true);
|
||||
if (ua.ie && ua.win) { storedAltContent.style.display = "block"; }
|
||||
}
|
||||
if (storedCallbackFn) { storedCallbackFn(storedCallbackObj); }
|
||||
}
|
||||
isExpressInstallActive = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}();
|
@ -1,218 +0,0 @@
|
||||
package
|
||||
{
|
||||
import flash.display.Sprite;
|
||||
import flash.events.Event;
|
||||
import flash.events.IOErrorEvent;
|
||||
import flash.events.ProgressEvent;
|
||||
import flash.events.TimerEvent;
|
||||
import flash.external.ExternalInterface;
|
||||
import flash.media.Sound;
|
||||
import flash.net.Socket;
|
||||
import flash.net.URLRequest;
|
||||
import flash.system.Security;
|
||||
import flash.utils.Timer;
|
||||
|
||||
|
||||
public class CIMBridge extends Sprite
|
||||
{
|
||||
internal var CIM_HOST:String = "127.0.0.1";
|
||||
internal var CIM_PORT:Number = 23456;
|
||||
internal const TIME_OUT :Number =10000;
|
||||
internal const RE_CONNECT_TIME :Number = 20000;
|
||||
internal var socket:Socket = new Socket();
|
||||
internal var froceOffline :Boolean = false;
|
||||
internal const MESSAGE_SEPARATE :String = '\b';
|
||||
/**
|
||||
* 服务端心跳请求命令
|
||||
*/
|
||||
internal const CMD_HEARTBEAT_REQUEST:String="S_H_RQ";
|
||||
/**
|
||||
* 客户端心跳响应命令
|
||||
*/
|
||||
internal const CMD_HEARTBEAT_RESPONSE:String ="C_H_RS";
|
||||
|
||||
internal var mBuffer :String = '';
|
||||
|
||||
public function CIMBridge()
|
||||
{
|
||||
|
||||
ExternalInterface.addCallback("connect",connect);
|
||||
ExternalInterface.addCallback("bindAccount",bindAccount);
|
||||
ExternalInterface.addCallback("getOfflineMessage",getOfflineMessage);
|
||||
ExternalInterface.addCallback("logout",logout);
|
||||
ExternalInterface.addCallback("playSound",playSound);
|
||||
|
||||
ExternalInterface.call("flashBridgeCreated");
|
||||
|
||||
}
|
||||
public function connect(host:String,port:Number):void
|
||||
{
|
||||
|
||||
CIM_HOST = host;
|
||||
CIM_PORT = port;
|
||||
var policyfile:String="xmlsocket://"+CIM_HOST+":"+CIM_PORT;
|
||||
Security.loadPolicyFile(policyfile);//加载安全策略文件,得到相应的返回才会创建连接
|
||||
socket.timeout = TIME_OUT;
|
||||
socket.addEventListener(Event.CONNECT,sessionCreated);//监听是否连接上服务器
|
||||
socket.addEventListener(Event.CLOSE,sessionClosed);//监听套接字连接是否关闭
|
||||
socket.addEventListener(IOErrorEvent.IO_ERROR,sessionFailed);//监听套接字连接是否失败
|
||||
socket.addEventListener(ProgressEvent.SOCKET_DATA,messageReceived); //监听服务器消息
|
||||
socket.connect(CIM_HOST,CIM_PORT);//连接服务器
|
||||
|
||||
|
||||
var timer:Timer = new Timer(TIME_OUT, 1);
|
||||
timer.addEventListener(TimerEvent.TIMER, function():void{
|
||||
if(socket.connected == false){
|
||||
sessionFailed(new IOErrorEvent(""));
|
||||
}
|
||||
});
|
||||
timer.start();
|
||||
|
||||
}
|
||||
|
||||
public function bindAccount(account:String,deviceId:String):void
|
||||
{
|
||||
var xml:String="<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
|
||||
xml+="<sent>";
|
||||
xml+="<key>client_bind</key>";
|
||||
xml+="<data>";
|
||||
xml+="<account>"+account+"</account>";
|
||||
xml+="<deviceId>"+deviceId+"</deviceId>";
|
||||
xml+="<channel>browse</channel>";
|
||||
xml+="<device>Flash</device>";
|
||||
xml+="<version>2.0.0</version>";
|
||||
xml+="<osVersion>"+flash.system.Capabilities.os+"</osVersion>";
|
||||
xml+="</data>";
|
||||
xml+="</sent>";
|
||||
|
||||
send(xml);
|
||||
|
||||
}
|
||||
|
||||
public function getOfflineMessage(account:String):void
|
||||
{
|
||||
|
||||
var xml:String="<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
|
||||
xml+="<sent>";
|
||||
xml+="<key>client_get_offline_message</key>";
|
||||
xml+="<data>";
|
||||
xml+="<account>"+account+"</account>";
|
||||
xml+="</data>";
|
||||
xml+="</sent>";
|
||||
send(xml);
|
||||
|
||||
}
|
||||
|
||||
public function logout():void
|
||||
{
|
||||
|
||||
socket.close();
|
||||
|
||||
}
|
||||
|
||||
private function sessionCreated(event:Event):void
|
||||
{
|
||||
|
||||
ExternalInterface.call("sessionCreated");
|
||||
froceOffline = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private function sessionClosed(event:Event):void
|
||||
{
|
||||
ExternalInterface.call("sessionClosed");
|
||||
|
||||
if(!froceOffline)
|
||||
{
|
||||
reconnection();
|
||||
}
|
||||
}
|
||||
|
||||
private function sessionFailed(event:Event):void
|
||||
{
|
||||
//每隔20秒重新连接
|
||||
|
||||
ExternalInterface.call("sessionFailed");
|
||||
|
||||
reconnection();
|
||||
|
||||
}
|
||||
|
||||
private function reconnection():void{
|
||||
var timer:Timer = new Timer(RE_CONNECT_TIME + Math.random() * 10, 1);
|
||||
timer.addEventListener(TimerEvent.TIMER, function():void{
|
||||
connect(CIM_HOST,CIM_PORT);
|
||||
});
|
||||
timer.start();
|
||||
|
||||
}
|
||||
|
||||
|
||||
internal function handleMessage(message:String):void{
|
||||
|
||||
if(message.toUpperCase() == CMD_HEARTBEAT_REQUEST)
|
||||
{
|
||||
send(CMD_HEARTBEAT_RESPONSE);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var xml:XML=XML(message);
|
||||
if(xml.name()=="reply"){
|
||||
ExternalInterface.call("onReplyReceived",ReplyBody.mappingToJSON(xml));
|
||||
}
|
||||
if(xml.name()=="message"){
|
||||
|
||||
|
||||
if(xml["type"]=="999")
|
||||
{
|
||||
froceOffline = true;
|
||||
}
|
||||
|
||||
ExternalInterface.call("onMessageReceived",Message.mappingToJSON(xml));
|
||||
}
|
||||
}
|
||||
|
||||
/**接受服务器信息*/
|
||||
internal function messageReceived(event:ProgressEvent):void
|
||||
{
|
||||
|
||||
mBuffer+=socket.readMultiByte(socket.bytesAvailable,"UTF-8");;
|
||||
if(mBuffer.charAt(mBuffer.length-1)!=MESSAGE_SEPARATE){
|
||||
|
||||
return ;
|
||||
|
||||
}else
|
||||
{
|
||||
var array:Array = mBuffer.split(MESSAGE_SEPARATE);
|
||||
for each(var message:String in array) {
|
||||
handleMessage(message);
|
||||
}
|
||||
|
||||
mBuffer = "";
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**发送数据到服务器*/
|
||||
internal function send(msg:String):void
|
||||
{
|
||||
//新建一个ByteArray来存放数据
|
||||
socket.writeUTFBytes(msg+MESSAGE_SEPARATE);
|
||||
//调用flush方法发送信息
|
||||
socket.flush();
|
||||
}
|
||||
|
||||
public function playSound(name:String):void
|
||||
{
|
||||
internal var _sound:Sound = new Sound(new URLRequest(name));
|
||||
_sound.play(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
|
||||
package
|
||||
{
|
||||
import com.adobe.serialization.json.JSON;
|
||||
|
||||
public class Message
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* 消息类型,用户自定义消息类别
|
||||
*/
|
||||
public var mid:String;
|
||||
|
||||
|
||||
/**
|
||||
* 消息类型,用户自定义消息类别
|
||||
*/
|
||||
public var type:String;
|
||||
/**
|
||||
* 消息标题
|
||||
*/
|
||||
public var title:String;
|
||||
/**
|
||||
* 消息类容,于type 组合为任何类型消息,content 根据 format 可表示为 text,json ,xml数据格式
|
||||
*/
|
||||
public var content:String = "";
|
||||
|
||||
|
||||
/**
|
||||
* 消息发送者账号
|
||||
*/
|
||||
public var sender:String;
|
||||
/**
|
||||
* 消息发送者接收者
|
||||
*/
|
||||
public var receiver:String;
|
||||
|
||||
/**
|
||||
* 文件 url
|
||||
*/
|
||||
public var file:String;
|
||||
/**
|
||||
* 文件类型
|
||||
*/
|
||||
public var fileType:String;
|
||||
|
||||
/**
|
||||
* content 内容格式
|
||||
*/
|
||||
public var format:String = "txt";
|
||||
|
||||
|
||||
public var timestamp:Number;
|
||||
|
||||
public static function mappingToJSON(xml:XML):Object
|
||||
{
|
||||
var message:Message = new Message();
|
||||
message.mid = xml["mid"];
|
||||
message.type = xml["type"];
|
||||
message.title = xml["title"];
|
||||
message.sender = xml["sender"];
|
||||
message.receiver = xml["receiver"];
|
||||
message.file = xml["file"];
|
||||
message.fileType = xml["fileType"];
|
||||
message.timestamp = xml["timestamp"];
|
||||
message.content =xml["content"];
|
||||
return com.adobe.serialization.json.JSON.encode(message).toString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
|
||||
package
|
||||
{
|
||||
import com.adobe.serialization.json.JSON;
|
||||
|
||||
|
||||
public class ReplyBody
|
||||
{
|
||||
public var key:String;
|
||||
public var code:String;
|
||||
public var message:String;
|
||||
public var data:Object = new Object();
|
||||
public var timestamp:Number;
|
||||
|
||||
public static function mappingToJSON(xml:XML):String
|
||||
{
|
||||
var body:ReplyBody = new ReplyBody();
|
||||
body.key = xml["key"];
|
||||
body.code = xml["code"];
|
||||
body.timestamp = xml["timestamp"];
|
||||
var list:XMLList = xml.elements("data").children();
|
||||
for each(var item:XML in list) {
|
||||
body.data[item.name().toString()] =item.toString();
|
||||
}
|
||||
|
||||
return com.adobe.serialization.json.JSON.encode(body);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
BIN
CIM客户端文档.doc
@ -1,7 +1,7 @@
|
||||
#说明:
|
||||
此开源版本为基础功能版本,只有消息推送的基础功能!netty版本,和mina版本结构和功能完全一致,大家可以选择自己喜欢的或者合适的版本学习或者使用!
|
||||
|
||||
#侣信专业版1.6.5版本发布
|
||||
#侣信专业版1.7.0版本发布
|
||||
#[http://farsunset.com](http://farsunset.com)
|
||||
|
||||
|
||||
|
@ -2,7 +2,9 @@
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="lib" path="/cim-server/WebRoot/WEB-INF/lib/mina-core-2.0.13.jar"/>
|
||||
<classpathentry kind="lib" path="C:/dev/android-sdk-windows/platforms/android-22/android.jar"/>
|
||||
<classpathentry kind="lib" path="libs/log4j-1.2.17.jar"/>
|
||||
<classpathentry kind="lib" path="D:/Program Files (x86)/dev/android-sdk-windos/platforms/android-21/android.jar"/>
|
||||
<classpathentry kind="lib" path="libs/mina-core-2.0.16.jar"/>
|
||||
<classpathentry kind="lib" path="libs/protobuf-java-3.2.0.jar"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
|
@ -0,0 +1,12 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
|
||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||
org.eclipse.jdt.core.compiler.compliance=1.7
|
||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.7
|
BIN
cim_for_mina/cim-android-sdk/libs/log4j-1.2.17.jar
Normal file
BIN
cim_for_mina/cim-android-sdk/libs/mina-core-2.0.16.jar
Normal file
BIN
cim_for_mina/cim-android-sdk/libs/protobuf-java-3.2.0.jar
Normal file
@ -1,11 +1,27 @@
|
||||
/**
|
||||
* probject:cim-android-sdk
|
||||
* @version 2.1.0
|
||||
*
|
||||
* @author 3979434@qq.com
|
||||
*/
|
||||
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.sdk.android;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
@ -14,15 +30,17 @@ import android.database.sqlite.SQLiteOpenHelper;
|
||||
class CIMCacheToolkit extends SQLiteOpenHelper {
|
||||
|
||||
private static final String DATABASE_NAME = "CIM_CONFIG_INFO.db";
|
||||
private static final int DATABASE_VERSION = 20160416;
|
||||
private static final int DATABASE_VERSION = 20160406;
|
||||
private static final String TABLE_NAME = "T_CIM_CONFIG";
|
||||
private static CIMCacheToolkit toolkit;
|
||||
|
||||
private static final String TABLE_SQL = "CREATE TABLE IF NOT EXISTS "+TABLE_NAME+" (KEY VARCHAR(64) PRIMARY KEY,VALUE TEXT)";
|
||||
|
||||
private static final String TABLE_SQL = "CREATE TABLE IF NOT EXISTS T_CIM_CONFIG (KEY VARCHAR(64) PRIMARY KEY,VALUE TEXT)";
|
||||
private static final String DELETE_SQL = "DELETE FROM "+TABLE_NAME+" WHERE KEY = ?";
|
||||
|
||||
private static final String DELETE_SQL = "DELETE FROM T_CIM_CONFIG WHERE KEY = ?";
|
||||
private static final String QUERY_SQL = "SELECT VALUE FROM "+TABLE_NAME+" WHERE KEY = ?";
|
||||
|
||||
private static final String SAVE_SQL = "INSERT INTO T_CIM_CONFIG (KEY,VALUE) VALUES(?,?)";
|
||||
|
||||
private static final String QUERY_SQL = "SELECT VALUE FROM T_CIM_CONFIG WHERE KEY = ?";
|
||||
private SQLiteDatabase mSQLiteDatabase;
|
||||
|
||||
public static final String CIM_CONFIG_INFO = "CIM_CONFIG_INFO";
|
||||
|
||||
@ -37,16 +55,15 @@ class CIMCacheToolkit extends SQLiteOpenHelper {
|
||||
public static final String KEY_CIM_SERVIER_PORT = "KEY_CIM_SERVIER_PORT";
|
||||
|
||||
public static final String KEY_CIM_CONNECTION_STATE = "KEY_CIM_CONNECTION_STATE";
|
||||
|
||||
private static CIMCacheToolkit toolkit;
|
||||
|
||||
private SQLiteDatabase mSQLiteDatabase;
|
||||
|
||||
|
||||
public synchronized static CIMCacheToolkit getInstance(Context context){
|
||||
if (toolkit==null){
|
||||
toolkit = new CIMCacheToolkit(context);
|
||||
}
|
||||
return toolkit;
|
||||
|
||||
if(toolkit==null){
|
||||
toolkit = new CIMCacheToolkit(context);
|
||||
}
|
||||
|
||||
return toolkit;
|
||||
}
|
||||
|
||||
|
||||
@ -59,7 +76,6 @@ class CIMCacheToolkit extends SQLiteOpenHelper {
|
||||
}
|
||||
|
||||
|
||||
|
||||
public synchronized void remove(String key)
|
||||
{
|
||||
getSQLiteDatabase().execSQL(DELETE_SQL,new String[]{key});
|
||||
@ -68,8 +84,15 @@ class CIMCacheToolkit extends SQLiteOpenHelper {
|
||||
|
||||
public synchronized void putString(String key,String value)
|
||||
{
|
||||
getSQLiteDatabase().execSQL(DELETE_SQL,new String[]{key});
|
||||
getSQLiteDatabase().execSQL(SAVE_SQL, new String[]{key, value});
|
||||
|
||||
ContentValues values = new ContentValues();
|
||||
values.put("VALUE", value);
|
||||
int result = getSQLiteDatabase().updateWithOnConflict(TABLE_NAME, values, "KEY=?",new String[]{key},SQLiteDatabase.CONFLICT_FAIL);
|
||||
if(result<=0){
|
||||
|
||||
values.put("KEY", key);
|
||||
getSQLiteDatabase().insert(TABLE_NAME, null, values);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -77,14 +100,15 @@ class CIMCacheToolkit extends SQLiteOpenHelper {
|
||||
{
|
||||
String value = null;
|
||||
Cursor cursor = getSQLiteDatabase().rawQuery(QUERY_SQL, new String[]{key});
|
||||
if (cursor!=null&&cursor.moveToFirst())
|
||||
if (cursor!=null)
|
||||
{
|
||||
value = cursor.getString(0);
|
||||
if(cursor.moveToFirst()){
|
||||
value = cursor.getString(0);
|
||||
}
|
||||
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@ -123,6 +147,8 @@ class CIMCacheToolkit extends SQLiteOpenHelper {
|
||||
try{toolkit.close();}catch(Exception e){}
|
||||
}
|
||||
|
||||
toolkit = null;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,15 +1,30 @@
|
||||
/**
|
||||
* probject:cim-android-sdk
|
||||
* @version 2.1.0
|
||||
*
|
||||
* @author 3979434@qq.com
|
||||
*/
|
||||
/**
|
||||
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.sdk.android;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.mina.core.future.ConnectFuture;
|
||||
import org.apache.mina.core.future.WriteFuture;
|
||||
@ -19,6 +34,7 @@ import org.apache.mina.core.session.IoSession;
|
||||
import org.apache.mina.filter.codec.ProtocolCodecFilter;
|
||||
import org.apache.mina.filter.keepalive.KeepAliveFilter;
|
||||
import org.apache.mina.filter.keepalive.KeepAliveMessageFactory;
|
||||
import org.apache.mina.filter.keepalive.KeepAliveRequestTimeoutHandler;
|
||||
import org.apache.mina.transport.socket.nio.NioSocketConnector;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@ -27,10 +43,11 @@ import android.net.NetworkInfo;
|
||||
import android.util.Log;
|
||||
|
||||
import com.farsunset.cim.sdk.android.constant.CIMConstant;
|
||||
import com.farsunset.cim.sdk.android.exception.CIMSessionDisableException;
|
||||
import com.farsunset.cim.sdk.android.exception.NetWorkDisableException;
|
||||
import com.farsunset.cim.sdk.android.exception.WriteToClosedSessionException;
|
||||
import com.farsunset.cim.sdk.android.exception.SessionDisconnectedException;
|
||||
import com.farsunset.cim.sdk.android.exception.NetworkDisconnectedException;
|
||||
import com.farsunset.cim.sdk.android.filter.ClientMessageCodecFactory;
|
||||
import com.farsunset.cim.sdk.android.model.HeartbeatRequest;
|
||||
import com.farsunset.cim.sdk.android.model.HeartbeatResponse;
|
||||
import com.farsunset.cim.sdk.android.model.Message;
|
||||
import com.farsunset.cim.sdk.android.model.ReplyBody;
|
||||
import com.farsunset.cim.sdk.android.model.SentBody;
|
||||
@ -40,65 +57,44 @@ import com.farsunset.cim.sdk.android.model.SentBody;
|
||||
*
|
||||
* @author 3979434@qq.com
|
||||
*/
|
||||
class CIMConnectorManager extends IoHandlerAdapter implements KeepAliveMessageFactory{
|
||||
class CIMConnectorManager extends IoHandlerAdapter implements KeepAliveMessageFactory {
|
||||
|
||||
final static String TAG = CIMConnectorManager.class.getSimpleName();
|
||||
private NioSocketConnector connector;
|
||||
private ConnectFuture connectFuture;
|
||||
private final String TAG = CIMConnectorManager.class.getSimpleName();
|
||||
private final int READ_BUFFER_SIZE = 2048;//bit
|
||||
private final int CONNECT_TIMEOUT = 10 * 1000;//秒
|
||||
private final int WRITE_TIMEOUT = 10 * 1000;//秒
|
||||
|
||||
Context context;
|
||||
|
||||
private final int BOTH_IDLE_TIME = 120;//秒
|
||||
|
||||
private final int HEARBEAT_TIME_OUT = 330 * 1000;// 收到服务端心跳请求超时时间 毫秒
|
||||
|
||||
private final int READ_IDLE_TIME = 120;//秒
|
||||
private final int HEARBEAT_TIME_OUT = (READ_IDLE_TIME + 20) * 1000;// 收到服务端心跳请求超时时间 毫秒
|
||||
private final String KEY_LAST_HEART_TIME = "KEY_LAST_HEART_TIME" ;
|
||||
|
||||
private NioSocketConnector connector;
|
||||
private ConnectFuture connectFuture;
|
||||
private ExecutorService executor = Executors.newFixedThreadPool(1);
|
||||
private Context context;
|
||||
|
||||
static CIMConnectorManager manager;
|
||||
private static CIMConnectorManager manager;
|
||||
|
||||
// 消息广播action
|
||||
public static final String ACTION_MESSAGE_RECEIVED = "com.farsunset.cim.MESSAGE_RECEIVED";
|
||||
|
||||
// 发送sendbody失败广播
|
||||
public static final String ACTION_SENT_FAILED = "com.farsunset.cim.SENT_FAILED";
|
||||
|
||||
// 发送sendbody成功广播
|
||||
public static final String ACTION_SENT_SUCCESSED = "com.farsunset.cim.SENT_SUCCESSED";
|
||||
// 链接意外关闭广播
|
||||
public static final String ACTION_CONNECTION_CLOSED = "com.farsunset.cim.CONNECTION_CLOSED";
|
||||
// 链接失败广播
|
||||
public static final String ACTION_CONNECTION_FAILED = "com.farsunset.cim.CONNECTION_FAILED";
|
||||
// 链接成功广播
|
||||
public static final String ACTION_CONNECTION_SUCCESSED = "com.farsunset.cim.CONNECTION_SUCCESSED";
|
||||
// 发送sendbody成功后获得replaybody回应广播
|
||||
public static final String ACTION_REPLY_RECEIVED = "com.farsunset.cim.REPLY_RECEIVED";
|
||||
// 网络变化广播
|
||||
public static final String ACTION_NETWORK_CHANGED = "android.net.conn.CONNECTIVITY_CHANGE";
|
||||
|
||||
// 未知异常
|
||||
public static final String ACTION_UNCAUGHT_EXCEPTION = "com.farsunset.cim.UNCAUGHT_EXCEPTION";
|
||||
|
||||
//重试连接
|
||||
public final static String ACTION_CONNECTION_RECOVERY = "com.farsunset.cim.CONNECTION_RECOVERY";
|
||||
|
||||
private ExecutorService executor;
|
||||
private CIMConnectorManager(Context ctx) {
|
||||
private CIMConnectorManager(Context ctx) {
|
||||
context = ctx;
|
||||
executor = Executors.newCachedThreadPool();
|
||||
|
||||
connector = new NioSocketConnector();
|
||||
connector.setConnectTimeoutMillis(10 * 1000);
|
||||
connector.setConnectTimeoutMillis(CONNECT_TIMEOUT);
|
||||
connector.getSessionConfig().setTcpNoDelay(true);
|
||||
connector.getSessionConfig().setBothIdleTime(BOTH_IDLE_TIME);
|
||||
connector.getSessionConfig().setReadBufferSize(2048);
|
||||
connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new ClientMessageCodecFactory()));
|
||||
connector.getSessionConfig().setKeepAlive(true);
|
||||
connector.getSessionConfig().setReadBufferSize(READ_BUFFER_SIZE);
|
||||
|
||||
KeepAliveFilter keepAliveaHandler = new KeepAliveFilter(this, IdleStatus.BOTH_IDLE);
|
||||
KeepAliveFilter keepAliveaHandler = new KeepAliveFilter(this);
|
||||
keepAliveaHandler.setRequestInterval(READ_IDLE_TIME);
|
||||
keepAliveaHandler.setRequestTimeoutHandler(KeepAliveRequestTimeoutHandler.NOOP);
|
||||
keepAliveaHandler.setForwardEvent(true);
|
||||
connector.getFilterChain().addLast("heartbeat", keepAliveaHandler);
|
||||
connector.setHandler(this);
|
||||
|
||||
|
||||
connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new ClientMessageCodecFactory()));
|
||||
connector.getFilterChain().addLast("heartbeat", keepAliveaHandler);
|
||||
|
||||
connector.setHandler(this);
|
||||
|
||||
}
|
||||
|
||||
@ -110,118 +106,103 @@ class CIMConnectorManager extends IoHandlerAdapter implements KeepAliveMessageFa
|
||||
|
||||
}
|
||||
|
||||
private synchronized void syncConnection(final String cimServerHost,final int cimServerPort) {
|
||||
private synchronized void syncConnection(final String host,final int port) {
|
||||
|
||||
if(isConnected()){
|
||||
return ;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
if(isConnected()){
|
||||
return ;
|
||||
}
|
||||
Log.i(TAG, "****************CIM正在连接服务器 "+host+":"+port+"......");
|
||||
|
||||
CIMCacheToolkit.getInstance(context).putBoolean(CIMCacheToolkit.KEY_CIM_CONNECTION_STATE, false);
|
||||
InetSocketAddress remoteSocketAddress = new InetSocketAddress(cimServerHost, cimServerPort);
|
||||
InetSocketAddress remoteSocketAddress = new InetSocketAddress(host, port);
|
||||
connectFuture = connector.connect(remoteSocketAddress);
|
||||
connectFuture.awaitUninterruptibly();
|
||||
connectFuture.getSession();
|
||||
} catch (Exception e) {
|
||||
|
||||
long interval = CIMConstant.RECONN_INTERVAL_TIME - (5*1000 - new Random().nextInt(15*1000));
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(ACTION_CONNECTION_FAILED);
|
||||
intent.putExtra("exception", e);
|
||||
intent.setAction(CIMConstant.IntentAction.ACTION_CONNECTION_FAILED);
|
||||
intent.putExtra(Exception.class.getName(), e);
|
||||
intent.putExtra("interval", interval);
|
||||
context.sendBroadcast(intent);
|
||||
|
||||
Log.e(TAG, "******************CIM连接服务器失败 "+cimServerHost+":"+cimServerPort);
|
||||
|
||||
}
|
||||
Log.e(TAG, "****************CIM连接服务器失败 "+host+":"+port+"......将在"+interval/1000+"秒后重新尝试连接");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void connect(final String cimServerHost, final int cimServerPort) {
|
||||
public void connect(final String host, final int port) {
|
||||
|
||||
|
||||
if (!netWorkAvailable(context)) {
|
||||
if (!isNetworkConnected(context)) {
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(ACTION_CONNECTION_FAILED);
|
||||
intent.putExtra("exception", new NetWorkDisableException());
|
||||
intent.setAction(CIMConstant.IntentAction.ACTION_CONNECTION_FAILED);
|
||||
intent.putExtra(Exception.class.getName(), new NetworkDisconnectedException());
|
||||
context.sendBroadcast(intent);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Future<?> future = executor.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
syncConnection(cimServerHost, cimServerPort);
|
||||
}
|
||||
});
|
||||
try {
|
||||
if(future.get()!=null)
|
||||
|
||||
executor.execute(new Runnable() {
|
||||
public void run()
|
||||
{
|
||||
connect(cimServerHost,cimServerPort);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
connect(cimServerHost,cimServerPort);
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
syncConnection(host, port);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public void send(final SentBody body) {
|
||||
public synchronized void send(SentBody body) {
|
||||
|
||||
|
||||
executor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
IoSession session = getCurrentSession();
|
||||
if(session!=null && session.isConnected())
|
||||
{
|
||||
WriteFuture wf = session.write(body);
|
||||
// 消息发送超时 10秒
|
||||
wf.awaitUninterruptibly(10, TimeUnit.SECONDS);
|
||||
|
||||
if (!wf.isWritten()) {
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(ACTION_SENT_FAILED);
|
||||
intent.putExtra("exception", new WriteToClosedSessionException());
|
||||
intent.putExtra("sentBody", body);
|
||||
context.sendBroadcast(intent);
|
||||
}
|
||||
}else
|
||||
{
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(ACTION_SENT_FAILED);
|
||||
intent.putExtra("exception", new CIMSessionDisableException());
|
||||
intent.putExtra("sentBody", body);
|
||||
context.sendBroadcast(intent);
|
||||
}
|
||||
}
|
||||
});
|
||||
boolean isSuccessed = false;
|
||||
|
||||
Throwable exception = new SessionDisconnectedException();
|
||||
|
||||
IoSession session = getCurrentSession();
|
||||
if(session!=null && session.isConnected())
|
||||
{
|
||||
WriteFuture wf = session.write(body);
|
||||
// 消息发送超时 5秒
|
||||
wf.awaitUninterruptibly(WRITE_TIMEOUT);
|
||||
isSuccessed = wf.isWritten();
|
||||
exception = wf.getException();
|
||||
}
|
||||
|
||||
if(!isSuccessed){
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(CIMConstant.IntentAction.ACTION_SENT_FAILED);
|
||||
intent.putExtra(Exception.class.getName(),exception);
|
||||
intent.putExtra(SentBody.class.getName(), body);
|
||||
context.sendBroadcast(intent);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
IoSession session = getCurrentSession();
|
||||
if (session != null) {
|
||||
session.closeNow();
|
||||
session.removeAttribute("account");
|
||||
}
|
||||
|
||||
if (connector != null && !connector.isDisposed()) {
|
||||
connector.dispose();
|
||||
}
|
||||
|
||||
|
||||
CIMCacheToolkit.destroy();
|
||||
|
||||
manager = null;
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
IoSession session = getCurrentSession();
|
||||
if (session == null ) {
|
||||
return false;
|
||||
}
|
||||
return session.isConnected() ;
|
||||
return session != null ;
|
||||
}
|
||||
|
||||
|
||||
@ -237,50 +218,46 @@ class CIMConnectorManager extends IoHandlerAdapter implements KeepAliveMessageFa
|
||||
|
||||
public IoSession getCurrentSession()
|
||||
{
|
||||
if(connector.getManagedSessionCount()>0)
|
||||
Map<Long,IoSession> sessions = connector.getManagedSessions();
|
||||
for(Long key:sessions.keySet())
|
||||
{
|
||||
for(Long key:connector.getManagedSessions().keySet())
|
||||
{
|
||||
return connector.getManagedSessions().get(key);
|
||||
IoSession session = sessions.get(key);
|
||||
if(session.isConnected()){
|
||||
return session;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void sessionCreated(IoSession session) throws Exception {
|
||||
|
||||
|
||||
Log.i(TAG, "******************CIM连接服务器成功:"+session.getLocalAddress());
|
||||
Log.i(TAG, "****************CIM连接服务器成功:"+session.getLocalAddress()+" NID:"+session.getId());
|
||||
|
||||
setLastHeartbeatTime(session);
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(ACTION_CONNECTION_SUCCESSED);
|
||||
intent.setAction(CIMConstant.IntentAction.ACTION_CONNECTION_SUCCESSED);
|
||||
context.sendBroadcast(intent);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void sessionOpened(IoSession session) throws Exception {
|
||||
session.getConfig().setBothIdleTime(180);
|
||||
}
|
||||
public void sessionClosed(IoSession session) {
|
||||
|
||||
@Override
|
||||
public void sessionClosed(IoSession session) throws Exception {
|
||||
|
||||
Log.e(TAG, "******************CIM与服务器断开连接:"+session.getLocalAddress());
|
||||
Log.e(TAG, "****************CIM与服务器断开连接:"+session.getLocalAddress()+" NID:"+session.getId());
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(ACTION_CONNECTION_CLOSED);
|
||||
intent.setAction(CIMConstant.IntentAction.ACTION_CONNECTION_CLOSED);
|
||||
context.sendBroadcast(intent);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sessionIdle(IoSession session, IdleStatus status)throws Exception {
|
||||
Log.d(TAG, "******************CIM与服务器连接空闲:"+session.getLocalAddress() + " isActive:" + session.isActive()+ " isConnected:" + session.isConnected());
|
||||
public void sessionIdle(IoSession session, IdleStatus status) {
|
||||
Log.d(TAG, "****************CIM "+status.toString().toUpperCase()+":"+session.getLocalAddress() +" NID:"+session.getId()+ " isConnected:" + session.isConnected());
|
||||
|
||||
/**
|
||||
* 用于解决,wifi情况下。偶而路由器与服务器断开连接时,客户端并没及时收到关闭事件
|
||||
@ -291,52 +268,57 @@ class CIMConnectorManager extends IoHandlerAdapter implements KeepAliveMessageFa
|
||||
if(System.currentTimeMillis() - lastHeartbeatTime >= HEARBEAT_TIME_OUT)
|
||||
{
|
||||
session.closeNow();
|
||||
Log.e(TAG, "****************CIM心跳超时 ,即将重新连接......"+" NID:"+session.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(IoSession session, Throwable cause)
|
||||
throws Exception {
|
||||
|
||||
public void exceptionCaught(IoSession session, Throwable cause) {
|
||||
|
||||
Log.e(TAG, "****************CIM连接出现未知异常:"+session.getLocalAddress()+" NID:"+session.getId());
|
||||
|
||||
if(cause!=null && cause.getMessage()!=null){
|
||||
Log.e(TAG, cause.getMessage());
|
||||
}
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(ACTION_UNCAUGHT_EXCEPTION);
|
||||
intent.putExtra("exception", cause);
|
||||
intent.setAction(CIMConstant.IntentAction.ACTION_UNCAUGHT_EXCEPTION);
|
||||
intent.putExtra(Exception.class.getName(), cause);
|
||||
context.sendBroadcast(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageReceived(IoSession session, Object obj)
|
||||
throws Exception {
|
||||
|
||||
public void messageReceived(IoSession session, Object obj){
|
||||
|
||||
if (obj instanceof Message) {
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(ACTION_MESSAGE_RECEIVED);
|
||||
intent.putExtra("message", (Message) obj);
|
||||
intent.setAction(CIMConstant.IntentAction.ACTION_MESSAGE_RECEIVED);
|
||||
intent.putExtra(Message.class.getName(), (Message) obj);
|
||||
context.sendBroadcast(intent);
|
||||
|
||||
}
|
||||
if (obj instanceof ReplyBody) {
|
||||
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(ACTION_REPLY_RECEIVED);
|
||||
intent.putExtra("replyBody", (ReplyBody) obj);
|
||||
intent.setAction(CIMConstant.IntentAction.ACTION_REPLY_RECEIVED);
|
||||
intent.putExtra(ReplyBody.class.getName(), (ReplyBody) obj);
|
||||
context.sendBroadcast(intent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageSent(IoSession session, Object message) throws Exception {
|
||||
public void messageSent(IoSession session, Object message) {
|
||||
if(message instanceof SentBody)
|
||||
{
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(ACTION_SENT_SUCCESSED);
|
||||
intent.putExtra("sentBody", (SentBody) message);
|
||||
intent.setAction(CIMConstant.IntentAction.ACTION_SENT_SUCCESSED);
|
||||
intent.putExtra(SentBody.class.getName(), (SentBody) message);
|
||||
context.sendBroadcast(intent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void setLastHeartbeatTime(IoSession session)
|
||||
{
|
||||
session.setAttribute(KEY_LAST_HEART_TIME, System.currentTimeMillis());
|
||||
@ -345,14 +327,14 @@ class CIMConnectorManager extends IoHandlerAdapter implements KeepAliveMessageFa
|
||||
private long getLastHeartbeatTime(IoSession session)
|
||||
{
|
||||
long time = 0;
|
||||
Object value ;
|
||||
if((value = session.getAttribute(KEY_LAST_HEART_TIME)) !=null){
|
||||
Object value = session.getAttribute(KEY_LAST_HEART_TIME);
|
||||
if(value !=null){
|
||||
time = Long.parseLong(value.toString());
|
||||
}
|
||||
return time;
|
||||
}
|
||||
|
||||
public static boolean netWorkAvailable(Context context) {
|
||||
public static boolean isNetworkConnected(Context context) {
|
||||
try {
|
||||
ConnectivityManager nw = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkInfo networkInfo = nw.getActiveNetworkInfo();
|
||||
@ -362,14 +344,15 @@ class CIMConnectorManager extends IoHandlerAdapter implements KeepAliveMessageFa
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object getRequest(IoSession arg0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getResponse(IoSession arg0, Object arg1) {
|
||||
return CIMConstant.CMD_HEARTBEAT_RESPONSE;
|
||||
public Object getResponse(IoSession session, Object arg1) {
|
||||
return HeartbeatResponse.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -377,12 +360,11 @@ class CIMConnectorManager extends IoHandlerAdapter implements KeepAliveMessageFa
|
||||
|
||||
setLastHeartbeatTime(session);
|
||||
|
||||
return CIMConstant.CMD_HEARTBEAT_REQUEST.equalsIgnoreCase(data.toString());
|
||||
return data instanceof HeartbeatRequest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isResponse(IoSession arg0, Object arg1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,30 @@
|
||||
/**
|
||||
* probject:cim-android-sdk
|
||||
* @version 2.1.0
|
||||
*
|
||||
* @author 3979434@qq.com
|
||||
*/
|
||||
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.sdk.android;
|
||||
|
||||
|
||||
|
||||
import com.farsunset.cim.sdk.android.constant.CIMConstant;
|
||||
import com.farsunset.cim.sdk.android.exception.CIMSessionDisableException;
|
||||
import com.farsunset.cim.sdk.android.exception.SessionDisconnectedException;
|
||||
import com.farsunset.cim.sdk.android.model.Message;
|
||||
import com.farsunset.cim.sdk.android.model.ReplyBody;
|
||||
import com.farsunset.cim.sdk.android.model.SentBody;
|
||||
@ -18,28 +34,24 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
import android.os.Handler;
|
||||
/**
|
||||
* 消息入口,所有消息都会经过这里
|
||||
*/
|
||||
public abstract class CIMEventBroadcastReceiver extends BroadcastReceiver implements CIMEventListener {
|
||||
public abstract class CIMEventBroadcastReceiver extends BroadcastReceiver{
|
||||
|
||||
public Context context;
|
||||
protected Context context;
|
||||
|
||||
@Override
|
||||
public void onReceive(Context ctx, Intent it) {
|
||||
public void onReceive(Context ctx, Intent intent) {
|
||||
|
||||
context = ctx;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* 操作事件广播,用于提高service存活率
|
||||
*/
|
||||
if(it.getAction().equals(Intent.ACTION_USER_PRESENT)
|
||||
||it.getAction().equals(Intent.ACTION_POWER_CONNECTED)
|
||||
||it.getAction().equals(Intent.ACTION_POWER_DISCONNECTED)
|
||||
)
|
||||
if(intent.getAction().equals(Intent.ACTION_USER_PRESENT)
|
||||
||intent.getAction().equals(Intent.ACTION_POWER_CONNECTED)
|
||||
||intent.getAction().equals(Intent.ACTION_POWER_DISCONNECTED))
|
||||
{
|
||||
startPushService();
|
||||
}
|
||||
@ -48,17 +60,16 @@ public abstract class CIMEventBroadcastReceiver extends BroadcastReceiver impl
|
||||
/*
|
||||
* 设备网络状态变化事件
|
||||
*/
|
||||
if(it.getAction().equals(CIMConnectorManager.ACTION_NETWORK_CHANGED))
|
||||
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_NETWORK_CHANGED))
|
||||
{
|
||||
ConnectivityManager connectivityManager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
android.net.NetworkInfo info = connectivityManager.getActiveNetworkInfo();
|
||||
onDevicesNetworkChanged(info);
|
||||
onDevicesNetworkChanged(connectivityManager.getActiveNetworkInfo());
|
||||
}
|
||||
|
||||
/*
|
||||
* cim断开服务器事件
|
||||
*/
|
||||
if(it.getAction().equals(CIMConnectorManager.ACTION_CONNECTION_CLOSED))
|
||||
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_CONNECTION_CLOSED))
|
||||
{
|
||||
onInnerConnectionClosed();
|
||||
}
|
||||
@ -66,15 +77,16 @@ public abstract class CIMEventBroadcastReceiver extends BroadcastReceiver impl
|
||||
/*
|
||||
* cim连接服务器失败事件
|
||||
*/
|
||||
if(it.getAction().equals(CIMConnectorManager.ACTION_CONNECTION_FAILED))
|
||||
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_CONNECTION_FAILED))
|
||||
{
|
||||
onInnerConnectionFailed((Exception) it.getSerializableExtra("exception"));
|
||||
long interval = intent.getLongExtra("interval", CIMConstant.RECONN_INTERVAL_TIME);
|
||||
onConnectionFailed((Exception) intent.getSerializableExtra(Exception.class.getName()),interval);
|
||||
}
|
||||
|
||||
/*
|
||||
* cim连接服务器成功事件
|
||||
*/
|
||||
if(it.getAction().equals(CIMConnectorManager.ACTION_CONNECTION_SUCCESSED))
|
||||
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_CONNECTION_SUCCESSED))
|
||||
{
|
||||
onInnerConnectionSuccessed();
|
||||
}
|
||||
@ -82,94 +94,84 @@ public abstract class CIMEventBroadcastReceiver extends BroadcastReceiver impl
|
||||
/*
|
||||
* 收到推送消息事件
|
||||
*/
|
||||
if(it.getAction().equals(CIMConnectorManager.ACTION_MESSAGE_RECEIVED))
|
||||
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_MESSAGE_RECEIVED))
|
||||
{
|
||||
onInnerMessageReceived((Message)it.getSerializableExtra("message"));
|
||||
onInnerMessageReceived((Message)intent.getSerializableExtra(Message.class.getName()),intent);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 获取收到replybody成功事件
|
||||
*/
|
||||
if(it.getAction().equals(CIMConnectorManager.ACTION_REPLY_RECEIVED))
|
||||
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_REPLY_RECEIVED))
|
||||
{
|
||||
onReplyReceived((ReplyBody)it.getSerializableExtra("replyBody"));
|
||||
onReplyReceived((ReplyBody)intent.getSerializableExtra(ReplyBody.class.getName()));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 获取sendbody发送失败事件
|
||||
*/
|
||||
if(it.getAction().equals(CIMConnectorManager.ACTION_SENT_FAILED))
|
||||
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_SENT_FAILED))
|
||||
{
|
||||
onSentFailed((Exception) it.getSerializableExtra("exception"),(SentBody)it.getSerializableExtra("sentBody"));
|
||||
Exception exception = (Exception) intent.getSerializableExtra(Exception.class.getName());
|
||||
SentBody sentBody = (SentBody)intent.getSerializableExtra(SentBody.class.getName());
|
||||
onSentFailed(exception,sentBody);
|
||||
}
|
||||
|
||||
/*
|
||||
* 获取sendbody发送成功事件
|
||||
*/
|
||||
if(it.getAction().equals(CIMConnectorManager.ACTION_SENT_SUCCESSED))
|
||||
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_SENT_SUCCESSED))
|
||||
{
|
||||
onSentSucceed((SentBody)it.getSerializableExtra("sentBody"));
|
||||
onSentSucceed((SentBody)intent.getSerializableExtra(SentBody.class.getName()));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 获取cim数据传输异常事件
|
||||
*/
|
||||
if(it.getAction().equals(CIMConnectorManager.ACTION_UNCAUGHT_EXCEPTION))
|
||||
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_UNCAUGHT_EXCEPTION))
|
||||
{
|
||||
onUncaughtException((Exception)it.getSerializableExtra("exception"));
|
||||
onUncaughtException((Exception)intent.getSerializableExtra(Exception.class.getName()));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 重新连接,如果断开的话
|
||||
*/
|
||||
if(it.getAction().equals(CIMConnectorManager.ACTION_CONNECTION_RECOVERY))
|
||||
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_CONNECTION_RECOVERY))
|
||||
{
|
||||
CIMPushManager.connect(context);
|
||||
CIMPushManager.connect(context,0);
|
||||
}
|
||||
}
|
||||
|
||||
private void startPushService()
|
||||
{
|
||||
private void startPushService(){
|
||||
Intent intent = new Intent(context, CIMPushService.class);
|
||||
intent.setAction(CIMPushManager.ACTION_ACTIVATE_PUSH_SERVICE);
|
||||
context.startService(intent);
|
||||
}
|
||||
|
||||
private void onInnerConnectionClosed(){
|
||||
CIMCacheToolkit.getInstance(context).putBoolean(CIMCacheToolkit.KEY_CIM_CONNECTION_STATE, false);
|
||||
if(CIMConnectorManager.netWorkAvailable(context))
|
||||
if(CIMConnectorManager.isNetworkConnected(context))
|
||||
{
|
||||
CIMPushManager.connect(context);
|
||||
CIMPushManager.connect(context,0);
|
||||
}
|
||||
|
||||
onConnectionClosed();
|
||||
}
|
||||
|
||||
Handler connectionHandler = new Handler(){
|
||||
@Override
|
||||
public void handleMessage(android.os.Message message){
|
||||
CIMPushManager.connect(context);
|
||||
}
|
||||
};
|
||||
|
||||
private void onInnerConnectionFailed(Exception e){
|
||||
private void onConnectionFailed(Exception e,long reinterval){
|
||||
|
||||
if(CIMConnectorManager.netWorkAvailable(context))
|
||||
if(CIMConnectorManager.isNetworkConnected(context))
|
||||
{
|
||||
connectionHandler.sendEmptyMessageDelayed(0, CIMConstant.RECONN_INTERVAL_TIME);
|
||||
onConnectionFailed();
|
||||
|
||||
CIMPushManager.connect(context,reinterval);
|
||||
}
|
||||
|
||||
onConnectionFailed(e);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private void onInnerConnectionSuccessed(){
|
||||
CIMCacheToolkit.getInstance(context).putBoolean(CIMCacheToolkit.KEY_CIM_CONNECTION_STATE, true);
|
||||
|
||||
@ -179,34 +181,36 @@ public abstract class CIMEventBroadcastReceiver extends BroadcastReceiver impl
|
||||
|
||||
private void onUncaughtException(Throwable arg0) {}
|
||||
|
||||
|
||||
|
||||
private void onDevicesNetworkChanged(NetworkInfo info) {
|
||||
|
||||
if(info !=null)
|
||||
{
|
||||
CIMPushManager.connect(context);
|
||||
CIMPushManager.connect(context,0);
|
||||
}
|
||||
|
||||
onNetworkChanged(info);
|
||||
}
|
||||
|
||||
private void onInnerMessageReceived(com.farsunset.cim.sdk.android.model.Message message)
|
||||
{
|
||||
if(CIMConstant.MessageType.TYPE_999.equals(message.getType()))
|
||||
private void onInnerMessageReceived(com.farsunset.cim.sdk.android.model.Message message, Intent intent){
|
||||
if(isForceOfflineMessage(message.getAction()))
|
||||
{
|
||||
CIMCacheToolkit.getInstance(context).putBoolean(CIMCacheToolkit.KEY_MANUAL_STOP,true);
|
||||
CIMPushManager.stop(context);
|
||||
}
|
||||
|
||||
onMessageReceived(message);
|
||||
onMessageReceived(message,intent);
|
||||
}
|
||||
|
||||
private void onSentFailed(Exception e, SentBody body){
|
||||
private boolean isForceOfflineMessage(String action)
|
||||
{
|
||||
return CIMConstant.MessageAction.ACTION_999.equals(action) || CIMConstant.MessageAction.ACTION_444.equals(action);
|
||||
}
|
||||
|
||||
private void onSentFailed(Exception e, SentBody body){
|
||||
|
||||
//与服务端端开链接,重新连接
|
||||
if(e instanceof CIMSessionDisableException)
|
||||
if(e instanceof SessionDisconnectedException)
|
||||
{
|
||||
CIMPushManager.connect(context);
|
||||
CIMPushManager.connect(context,0);
|
||||
}else
|
||||
{
|
||||
//发送失败 重新发送
|
||||
@ -215,13 +219,32 @@ public abstract class CIMEventBroadcastReceiver extends BroadcastReceiver impl
|
||||
|
||||
}
|
||||
|
||||
private void onSentSucceed(SentBody body){}
|
||||
@Override
|
||||
public abstract void onMessageReceived(Message message);
|
||||
@Override
|
||||
public abstract void onReplyReceived(ReplyBody body);
|
||||
public abstract void onNetworkChanged(NetworkInfo info);
|
||||
public abstract void onConnectionFailed(Exception e);
|
||||
|
||||
|
||||
public abstract void onMessageReceived(com.farsunset.cim.sdk.android.model.Message message,Intent intent);
|
||||
|
||||
public void onNetworkChanged(NetworkInfo info) {
|
||||
CIMListenerManager.notifyOnNetworkChanged(info);
|
||||
}
|
||||
|
||||
|
||||
public void onConnectionSuccessed(boolean hasAutoBind) {
|
||||
CIMListenerManager.notifyOnConnectionSuccessed(hasAutoBind);
|
||||
}
|
||||
|
||||
public void onConnectionClosed() {
|
||||
CIMListenerManager.notifyOnConnectionClosed();
|
||||
}
|
||||
|
||||
public void onConnectionFailed() {
|
||||
CIMListenerManager.notifyOnConnectionFailed();
|
||||
}
|
||||
|
||||
public void onReplyReceived(ReplyBody body) {
|
||||
CIMListenerManager.notifyOnReplyReceived(body);
|
||||
}
|
||||
|
||||
public void onSentSucceed(SentBody body){
|
||||
CIMListenerManager.notifyOnSentSucceed(body);
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,31 @@
|
||||
/**
|
||||
* probject:cim-android-sdk
|
||||
* @version 2.1.0
|
||||
*
|
||||
* @author 3979434@qq.com
|
||||
*/
|
||||
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.sdk.android;
|
||||
|
||||
import android.net.NetworkInfo;
|
||||
|
||||
import com.farsunset.cim.sdk.android.model.Message;
|
||||
import com.farsunset.cim.sdk.android.model.ReplyBody;
|
||||
import com.farsunset.cim.sdk.android.model.SentBody;
|
||||
|
||||
/**
|
||||
*CIM 主要事件接口
|
||||
@ -22,36 +38,49 @@ public interface CIMEventListener
|
||||
* 当收到服务端推送过来的消息时调用
|
||||
* @param message
|
||||
*/
|
||||
public abstract void onMessageReceived(Message message);
|
||||
void onMessageReceived(Message message);
|
||||
|
||||
/**
|
||||
* 当调用CIMPushManager.sendRequest()向服务端发送请求,获得相应时调用
|
||||
* @param replybody
|
||||
*/
|
||||
public abstract void onReplyReceived(ReplyBody replybody);
|
||||
void onReplyReceived(ReplyBody replybody);
|
||||
|
||||
/**
|
||||
* 当调用CIMPushManager.sendRequest()向服务端发送请求成功时
|
||||
* @param body
|
||||
*/
|
||||
void onSentSuccessed(SentBody body);
|
||||
|
||||
|
||||
/**
|
||||
* 当手机网络发生变化时调用
|
||||
* @param networkinfo
|
||||
*/
|
||||
public abstract void onNetworkChanged(NetworkInfo networkinfo);
|
||||
void onNetworkChanged(NetworkInfo networkinfo);
|
||||
|
||||
|
||||
/**
|
||||
* 当连接服务器成功时回调
|
||||
* @param hasAutoBind : true 已经自动绑定账号到服务器了,不需要再手动调用bindAccount
|
||||
*/
|
||||
public abstract void onConnectionSuccessed(boolean hasAutoBind);
|
||||
void onConnectionSuccessed(boolean hasAutoBind);
|
||||
|
||||
/**
|
||||
* 当断开服务器连接的时候回调
|
||||
*/
|
||||
public abstract void onConnectionClosed();
|
||||
|
||||
/**
|
||||
* 当服务器连接失败的时候回调
|
||||
*
|
||||
*/
|
||||
public abstract void onConnectionFailed(Exception e);
|
||||
void onConnectionClosed();
|
||||
|
||||
/**
|
||||
* 当连接服务器失败的时候回调
|
||||
*
|
||||
*/
|
||||
void onConnectionFailed();
|
||||
|
||||
/**
|
||||
* 监听器在容器里面的排序。值越大则越先接收
|
||||
*/
|
||||
int getEventDispatchOrder();
|
||||
}
|
||||
|
||||
|
@ -1,22 +1,33 @@
|
||||
/**
|
||||
* probject:cim-android-sdk
|
||||
* @version 2.1.0
|
||||
*
|
||||
* @author 3979434@qq.com
|
||||
*/
|
||||
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.sdk.android;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
|
||||
import com.farsunset.cim.sdk.android.constant.CIMConstant;
|
||||
import com.farsunset.cim.sdk.android.model.Message;
|
||||
import com.farsunset.cim.sdk.android.model.ReplyBody;
|
||||
import com.farsunset.cim.sdk.android.model.SentBody;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.NetworkInfo;
|
||||
import android.util.Log;
|
||||
|
||||
@ -27,15 +38,13 @@ import android.util.Log;
|
||||
public class CIMListenerManager {
|
||||
|
||||
private static ArrayList<CIMEventListener> cimListeners = new ArrayList<CIMEventListener>();
|
||||
private static CIMMessageReceiveComparator comparator = new CIMMessageReceiveComparator();
|
||||
|
||||
|
||||
|
||||
public static void registerMessageListener(CIMEventListener listener,Context mcontext) {
|
||||
public static void registerMessageListener(CIMEventListener listener) {
|
||||
|
||||
if (!cimListeners.contains(listener)) {
|
||||
cimListeners.add(listener);
|
||||
// 按照接收顺序倒序
|
||||
Collections.sort(cimListeners, new CIMMessageReceiveComparator(mcontext));
|
||||
Collections.sort(cimListeners,comparator);
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,6 +82,12 @@ public class CIMListenerManager {
|
||||
}
|
||||
}
|
||||
|
||||
public static void notifyOnConnectionFailed() {
|
||||
for (CIMEventListener listener : cimListeners) {
|
||||
listener.onConnectionFailed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void notifyOnReplyReceived(ReplyBody body) {
|
||||
for (CIMEventListener listener : cimListeners) {
|
||||
@ -80,11 +95,12 @@ public class CIMListenerManager {
|
||||
}
|
||||
}
|
||||
|
||||
public static void notifyOnConnectionFailed(Exception e) {
|
||||
public static void notifyOnSentSucceed(SentBody body) {
|
||||
for (CIMEventListener listener : cimListeners) {
|
||||
listener.onConnectionFailed(e);
|
||||
listener.onSentSuccessed(body);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void destory() {
|
||||
cimListeners.clear();
|
||||
@ -99,47 +115,17 @@ public class CIMListenerManager {
|
||||
/**
|
||||
* 消息接收activity的接收顺序排序,CIM_RECEIVE_ORDER倒序
|
||||
*/
|
||||
static class CIMMessageReceiveComparator implements Comparator<CIMEventListener>{
|
||||
private static class CIMMessageReceiveComparator implements Comparator<CIMEventListener>{
|
||||
|
||||
Context mcontext;
|
||||
public CIMMessageReceiveComparator(Context ctx)
|
||||
{
|
||||
mcontext = ctx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(CIMEventListener arg1, CIMEventListener arg2) {
|
||||
|
||||
Integer order1 = CIMConstant.CIM_DEFAULT_MESSAGE_ORDER;
|
||||
Integer order2 = CIMConstant.CIM_DEFAULT_MESSAGE_ORDER;
|
||||
ActivityInfo info;
|
||||
if (arg1 instanceof Activity ) {
|
||||
|
||||
try {
|
||||
info = mcontext.getPackageManager() .getActivityInfo(((Activity)(arg1)).getComponentName(), PackageManager.GET_META_DATA);
|
||||
if(info.metaData!=null)
|
||||
{
|
||||
order1 = info.metaData.getInt("CIM_RECEIVE_ORDER");
|
||||
}
|
||||
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
|
||||
if (arg1 instanceof Activity ) {
|
||||
try {
|
||||
info = mcontext.getPackageManager() .getActivityInfo(((Activity)(arg2)).getComponentName(), PackageManager.GET_META_DATA);
|
||||
if(info.metaData!=null)
|
||||
{
|
||||
order2 = info.metaData.getInt("CIM_RECEIVE_ORDER");
|
||||
}
|
||||
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
|
||||
return order2.compareTo(order1);
|
||||
int order1 = arg1.getEventDispatchOrder();
|
||||
int order2 = arg2.getEventDispatchOrder();
|
||||
return order2 - order1 ;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,9 +1,24 @@
|
||||
/**
|
||||
* probject:cim-android-sdk
|
||||
* @version 2.1.0
|
||||
*
|
||||
* @author 3979434@qq.com
|
||||
*/
|
||||
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.sdk.android;
|
||||
import java.util.UUID;
|
||||
|
||||
@ -33,27 +48,20 @@ public class CIMPushManager {
|
||||
|
||||
static String KEY_SEND_BODY ="KEY_SEND_BODY";
|
||||
|
||||
static String KEY_CIM_CONNECTION_STATUS ="KEY_CIM_CONNECTION_STATUS";
|
||||
|
||||
//被销毁的destroy()
|
||||
public static final int STATE_DESTROYED = 0x0000DE;
|
||||
//被销停止的 stop()
|
||||
public static final int STATE_STOPED = 0x0000EE;
|
||||
|
||||
public static final int STATE_NORMAL = 0x000000;
|
||||
/**
|
||||
* 初始化,连接服务端,在程序启动页或者 在Application里调用
|
||||
* @param context
|
||||
* @param ip
|
||||
* @param port
|
||||
*/
|
||||
public static void connect(Context context,String host,int port){
|
||||
public static void connect(Context context,String host,int port){
|
||||
|
||||
connect(context,host,port,false);
|
||||
connect(context,host,port,false,0);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static void connect(Context context,String ip,int port,boolean autoBind){
|
||||
private static void connect(Context context,String ip,int port,boolean autoBind,long delayedTime){
|
||||
|
||||
CIMCacheToolkit.getInstance(context).putBoolean(CIMCacheToolkit.KEY_CIM_DESTROYED, false);
|
||||
CIMCacheToolkit.getInstance(context).putBoolean(CIMCacheToolkit.KEY_MANUAL_STOP, false);
|
||||
@ -69,12 +77,13 @@ private static void connect(Context context,String ip,int port,boolean autoBind
|
||||
Intent serviceIntent = new Intent(context, CIMPushService.class);
|
||||
serviceIntent.putExtra(CIMCacheToolkit.KEY_CIM_SERVIER_HOST, ip);
|
||||
serviceIntent.putExtra(CIMCacheToolkit.KEY_CIM_SERVIER_PORT, port);
|
||||
serviceIntent.putExtra(CIMPushService.KEY_DELAYED_TIME, delayedTime);
|
||||
serviceIntent.setAction(ACTION_CREATE_CIM_CONNECTION);
|
||||
context.startService(serviceIntent);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
protected static void connect(Context context){
|
||||
protected static void connect(Context context,long delayedTime){
|
||||
|
||||
boolean isManualStop = CIMCacheToolkit.getInstance(context).getBoolean(CIMCacheToolkit.KEY_MANUAL_STOP);
|
||||
boolean isManualDestory = CIMCacheToolkit.getInstance(context).getBoolean(CIMCacheToolkit.KEY_CIM_DESTROYED);
|
||||
@ -87,9 +96,9 @@ private static void connect(Context context,String ip,int port,boolean autoBind
|
||||
String host = CIMCacheToolkit.getInstance(context).getString( CIMCacheToolkit.KEY_CIM_SERVIER_HOST);
|
||||
int port =CIMCacheToolkit.getInstance(context).getInt( CIMCacheToolkit.KEY_CIM_SERVIER_PORT);
|
||||
|
||||
connect(context,host,port,true);
|
||||
connect(context,host,port,true,delayedTime);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@ -104,6 +113,7 @@ private static void connect(Context context,String ip,int port,boolean autoBind
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
sendBindRequest(context,account);
|
||||
|
||||
}
|
||||
@ -132,8 +142,7 @@ private static void connect(Context context,String ip,int port,boolean autoBind
|
||||
|
||||
String account = CIMCacheToolkit.getInstance(context).getString(CIMCacheToolkit.KEY_ACCOUNT);
|
||||
boolean isManualDestory = CIMCacheToolkit.getInstance(context).getBoolean(CIMCacheToolkit.KEY_CIM_DESTROYED);
|
||||
boolean isManualStoped = CIMCacheToolkit.getInstance(context).getBoolean(CIMCacheToolkit.KEY_MANUAL_STOP);
|
||||
if( isManualStoped || account==null || account.trim().length()==0 || isManualDestory )
|
||||
if( account==null || account.trim().length()==0 || isManualDestory )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -195,7 +204,7 @@ private static void connect(Context context,String ip,int port,boolean autoBind
|
||||
|
||||
|
||||
CIMCacheToolkit.getInstance(context).putBoolean(CIMCacheToolkit.KEY_CIM_DESTROYED, true);
|
||||
CIMCacheToolkit.getInstance(context).remove(CIMCacheToolkit.KEY_ACCOUNT);
|
||||
CIMCacheToolkit.getInstance(context).putString(CIMCacheToolkit.KEY_ACCOUNT, null);
|
||||
|
||||
Intent serviceIntent = new Intent(context, CIMPushService.class);
|
||||
serviceIntent.setAction(ACTION_DESTORY);
|
||||
@ -205,9 +214,8 @@ private static void connect(Context context,String ip,int port,boolean autoBind
|
||||
|
||||
|
||||
/**
|
||||
* 重新恢复接收推送,重新连接服务端,并登录当前账号如果aotuBind == true
|
||||
* 重新恢复接收推送,重新连接服务端,并登录当前账号
|
||||
* @param context
|
||||
* @param aotuBind
|
||||
*/
|
||||
public static void resume(Context context){
|
||||
|
||||
@ -223,19 +231,7 @@ private static void connect(Context context,String ip,int port,boolean autoBind
|
||||
return CIMCacheToolkit.getInstance(context).getBoolean(CIMCacheToolkit.KEY_CIM_CONNECTION_STATE);
|
||||
}
|
||||
|
||||
public static int getState(Context context){
|
||||
boolean isManualDestory = CIMCacheToolkit.getInstance(context).getBoolean(CIMCacheToolkit.KEY_CIM_DESTROYED);
|
||||
if(isManualDestory){
|
||||
return STATE_DESTROYED;
|
||||
}
|
||||
|
||||
boolean isManualStop = CIMCacheToolkit.getInstance(context).getBoolean(CIMCacheToolkit.KEY_MANUAL_STOP);
|
||||
if(isManualStop){
|
||||
return STATE_STOPED;
|
||||
}
|
||||
|
||||
return STATE_NORMAL;
|
||||
}
|
||||
|
||||
|
||||
private static String getVersionName(Context context) {
|
||||
String versionName = null;
|
||||
@ -246,5 +242,5 @@ private static void connect(Context context,String ip,int port,boolean autoBind
|
||||
}
|
||||
return versionName;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,54 +1,88 @@
|
||||
/**
|
||||
* probject:cim-android-sdk
|
||||
* @version 2.1.0
|
||||
*
|
||||
* @author 3979434@qq.com
|
||||
*/
|
||||
/**
|
||||
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.sdk.android;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.PowerManager;
|
||||
import android.os.PowerManager.WakeLock;
|
||||
import android.os.Message;
|
||||
import android.util.Log;
|
||||
|
||||
import com.farsunset.cim.sdk.android.model.SentBody;
|
||||
|
||||
|
||||
/**
|
||||
* 与服务端连接服务
|
||||
* @author 3979434
|
||||
*
|
||||
*/
|
||||
public class CIMPushService extends Service {
|
||||
final static String TAG = CIMPushService.class.getSimpleName();
|
||||
protected final static int DEF_CIM_PORT = 28888;
|
||||
CIMConnectorManager manager;
|
||||
WakeLock wakeLock;
|
||||
private final String TAG = CIMPushService.class.getSimpleName();
|
||||
public final static String KEY_DELAYED_TIME ="KEY_DELAYED_TIME";
|
||||
private CIMConnectorManager manager;
|
||||
@Override
|
||||
public void onCreate()
|
||||
{
|
||||
manager = CIMConnectorManager.getManager(this.getApplicationContext());
|
||||
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
|
||||
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, CIMPushService.class.getName());
|
||||
}
|
||||
|
||||
|
||||
Handler connectionHandler = new Handler(){
|
||||
@Override
|
||||
public void handleMessage(android.os.Message message){
|
||||
|
||||
connectionHandler.removeMessages(0);
|
||||
|
||||
String host = message.getData().getString(CIMCacheToolkit.KEY_CIM_SERVIER_HOST);
|
||||
int port = message.getData().getInt(CIMCacheToolkit.KEY_CIM_SERVIER_PORT,0);
|
||||
manager.connect(host, port);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent,int flags, int startId) {
|
||||
|
||||
if(intent==null)
|
||||
{
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
intent = (intent == null ? new Intent(CIMPushManager.ACTION_ACTIVATE_PUSH_SERVICE) : intent);
|
||||
|
||||
String action = intent.getAction();
|
||||
|
||||
if(CIMPushManager.ACTION_CREATE_CIM_CONNECTION.equals(action))
|
||||
{
|
||||
String host = CIMCacheToolkit.getInstance(this).getString(CIMCacheToolkit.KEY_CIM_SERVIER_HOST);
|
||||
int port =CIMCacheToolkit.getInstance(this).getInt(CIMCacheToolkit.KEY_CIM_SERVIER_PORT);
|
||||
manager.connect(host,port);
|
||||
|
||||
long delayMillis = intent.getLongExtra(KEY_DELAYED_TIME,0);
|
||||
if( delayMillis > 0){
|
||||
|
||||
Message msg = connectionHandler.obtainMessage();
|
||||
msg.what = 0;
|
||||
msg.setData(intent.getExtras());
|
||||
connectionHandler.sendMessageDelayed(msg, delayMillis);
|
||||
|
||||
}else
|
||||
{
|
||||
String host = intent.getStringExtra(CIMCacheToolkit.KEY_CIM_SERVIER_HOST);
|
||||
int port = intent.getIntExtra(CIMCacheToolkit.KEY_CIM_SERVIER_PORT,0);
|
||||
manager.connect(host,port);
|
||||
}
|
||||
}
|
||||
|
||||
if(CIMPushManager.ACTION_SEND_REQUEST_BODY.equals(action))
|
||||
@ -65,7 +99,6 @@ import com.farsunset.cim.sdk.android.model.SentBody;
|
||||
{
|
||||
manager.destroy();
|
||||
this.stopSelf();
|
||||
android.os.Process.killProcess(android.os.Process.myPid());
|
||||
}
|
||||
|
||||
if(CIMPushManager.ACTION_ACTIVATE_PUSH_SERVICE.equals(action) )
|
||||
@ -73,42 +106,23 @@ import com.farsunset.cim.sdk.android.model.SentBody;
|
||||
if(!manager.isConnected()){
|
||||
|
||||
boolean isManualStop = CIMCacheToolkit.getInstance(this).getBoolean(CIMCacheToolkit.KEY_MANUAL_STOP);
|
||||
Log.i(TAG, "CIM.isConnected() == false, isManualStop == " + isManualStop);
|
||||
CIMPushManager.connect(this);
|
||||
|
||||
Log.w(TAG, "manager.isConnected() == false, isManualStop == " + isManualStop);
|
||||
CIMPushManager.connect(this,0);
|
||||
|
||||
}else
|
||||
{
|
||||
Log.i(TAG, "CIM.isConnected() == true");
|
||||
Log.i(TAG, "manager.isConnected() == true");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
try{
|
||||
if(!wakeLock.isHeld())
|
||||
{
|
||||
this.wakeLock.acquire();
|
||||
}
|
||||
}catch(Exception e){}
|
||||
|
||||
|
||||
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
|
||||
public void onDestroy()
|
||||
{
|
||||
super.onDestroy();
|
||||
if(wakeLock.isHeld())
|
||||
{
|
||||
this.wakeLock.release();
|
||||
wakeLock = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent arg0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,9 +1,24 @@
|
||||
/**
|
||||
* probject:cim-android-sdk
|
||||
* @version 2.1.0
|
||||
*
|
||||
* @author 3979434@qq.com
|
||||
*/
|
||||
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.sdk.android.constant;
|
||||
|
||||
/**
|
||||
@ -11,57 +26,90 @@ package com.farsunset.cim.sdk.android.constant;
|
||||
*/
|
||||
public interface CIMConstant {
|
||||
|
||||
long RECONN_INTERVAL_TIME= 30 * 1000;
|
||||
|
||||
public static String UTF8="UTF-8";
|
||||
|
||||
public static byte MESSAGE_SEPARATE='\b';
|
||||
|
||||
public static long RECONN_INTERVAL_TIME= 30 * 1000;
|
||||
|
||||
public static int CIM_DEFAULT_MESSAGE_ORDER=1;
|
||||
|
||||
public static class ReturnCode{
|
||||
//消息头长度为3个字节,第一个字节为消息类型,第二,第三字节 转换int后为消息长度
|
||||
int DATA_HEADER_LENGTH = 3;
|
||||
public static interface ReturnCode{
|
||||
|
||||
public static String CODE_404 ="404";
|
||||
String CODE_404 ="404";
|
||||
|
||||
public static String CODE_403 ="403";
|
||||
String CODE_403 ="403";
|
||||
|
||||
public static String CODE_405 ="405";
|
||||
String CODE_405 ="405";
|
||||
|
||||
public static String CODE_200 ="200";
|
||||
String CODE_200 ="200";
|
||||
|
||||
public static String CODE_206 ="206";
|
||||
String CODE_206 ="206";
|
||||
|
||||
public static String CODE_500 ="500";
|
||||
String CODE_500 ="500";
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 服务端心跳请求命令 cmd_server_hb_request
|
||||
*/
|
||||
public static final String CMD_HEARTBEAT_REQUEST="S_H_RQ";
|
||||
/**
|
||||
* 客户端心跳响应命令 cmd_client_hb_response
|
||||
*/
|
||||
public static final String CMD_HEARTBEAT_RESPONSE ="C_H_RS";
|
||||
|
||||
|
||||
public static class RequestKey{
|
||||
|
||||
|
||||
public static interface ProtobufType{
|
||||
byte C_H_RS = 0;
|
||||
byte S_H_RQ = 1;
|
||||
byte MESSAGE = 2;
|
||||
byte SENTBODY = 3;
|
||||
byte REPLYBODY = 4;
|
||||
}
|
||||
|
||||
public static interface RequestKey{
|
||||
|
||||
|
||||
public static String CLIENT_BIND ="client_bind";
|
||||
String CLIENT_BIND ="client_bind";
|
||||
|
||||
public static String CLIENT_OFFLINE_MESSAGE ="client_get_offline_message";
|
||||
String CLIENT_LOGOUT ="client_logout";
|
||||
|
||||
@Deprecated
|
||||
String CLIENT_PULL_MESSAGE ="client_pull_message";
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static class MessageType{
|
||||
public static interface MessageAction{
|
||||
|
||||
//用户会 踢出下线消息类型
|
||||
public static String TYPE_999 ="999";
|
||||
|
||||
}
|
||||
//被其他设备登录挤下线消息
|
||||
String ACTION_999 ="999";
|
||||
//被系统禁用消息
|
||||
String ACTION_444 ="444";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static interface IntentAction{
|
||||
|
||||
// 消息广播action
|
||||
String ACTION_MESSAGE_RECEIVED = "com.farsunset.cim.MESSAGE_RECEIVED";
|
||||
|
||||
// 发送sendbody失败广播
|
||||
String ACTION_SENT_FAILED = "com.farsunset.cim.SENT_FAILED";
|
||||
|
||||
// 发送sendbody成功广播
|
||||
String ACTION_SENT_SUCCESSED = "com.farsunset.cim.SENT_SUCCESSED";
|
||||
|
||||
// 链接意外关闭广播
|
||||
String ACTION_CONNECTION_CLOSED = "com.farsunset.cim.CONNECTION_CLOSED";
|
||||
|
||||
// 链接失败广播
|
||||
String ACTION_CONNECTION_FAILED = "com.farsunset.cim.CONNECTION_FAILED";
|
||||
|
||||
// 链接成功广播
|
||||
String ACTION_CONNECTION_SUCCESSED = "com.farsunset.cim.CONNECTION_SUCCESSED";
|
||||
|
||||
// 发送sendbody成功后获得replaybody回应广播
|
||||
String ACTION_REPLY_RECEIVED = "com.farsunset.cim.REPLY_RECEIVED";
|
||||
|
||||
// 网络变化广播
|
||||
String ACTION_NETWORK_CHANGED = "android.net.conn.CONNECTIVITY_CHANGE";
|
||||
|
||||
// 未知异常
|
||||
String ACTION_UNCAUGHT_EXCEPTION = "com.farsunset.cim.UNCAUGHT_EXCEPTION";
|
||||
|
||||
//重试连接
|
||||
String ACTION_CONNECTION_RECOVERY = "com.farsunset.cim.CONNECTION_RECOVERY";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,21 +0,0 @@
|
||||
/**
|
||||
* probject:cim-android-sdk
|
||||
* @version 2.1.0
|
||||
*
|
||||
* @author 3979434@qq.com
|
||||
*/
|
||||
package com.farsunset.cim.sdk.android.exception;
|
||||
|
||||
|
||||
public class CIMSessionDisableException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public CIMSessionDisableException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public CIMSessionDisableException(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
/**
|
||||
* probject:cim-android-sdk
|
||||
* @version 2.1.0
|
||||
*
|
||||
* @author 3979434@qq.com
|
||||
*/
|
||||
package com.farsunset.cim.sdk.android.exception;
|
||||
|
||||
|
||||
public class NetWorkDisableException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public NetWorkDisableException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public NetWorkDisableException(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.sdk.android.exception;
|
||||
|
||||
|
||||
public class NetworkDisconnectedException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public NetworkDisconnectedException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public NetworkDisconnectedException(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.sdk.android.exception;
|
||||
|
||||
|
||||
public class SessionDisconnectedException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public SessionDisconnectedException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public SessionDisconnectedException(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
/**
|
||||
* probject:cim-android-sdk
|
||||
* @version 2.1.0
|
||||
*
|
||||
* @author 3979434@qq.com
|
||||
*/
|
||||
package com.farsunset.cim.sdk.android.exception;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
public class WriteToClosedSessionException extends Exception implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public WriteToClosedSessionException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public WriteToClosedSessionException(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
@ -1,9 +1,24 @@
|
||||
/**
|
||||
* probject:cim-android-sdk
|
||||
* @version 2.1.0
|
||||
*
|
||||
* @author 3979434@qq.com
|
||||
*/
|
||||
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.sdk.android.filter;
|
||||
|
||||
import org.apache.mina.core.session.IoSession;
|
||||
@ -12,33 +27,28 @@ import org.apache.mina.filter.codec.ProtocolDecoder;
|
||||
import org.apache.mina.filter.codec.ProtocolEncoder;
|
||||
|
||||
/**
|
||||
* android客户端端消息 编码解码器, 可以在
|
||||
* 关于消息加密与加密, 可在 encoder时进行消息加密,在ServerMessageCodecFactory的 decoder时对消息解密
|
||||
* android客户端端消息 编码解码器
|
||||
*/
|
||||
public class ClientMessageCodecFactory implements ProtocolCodecFactory {
|
||||
|
||||
/**
|
||||
* 消息编码器
|
||||
*/
|
||||
private final ClientMessageEncoder encoder;
|
||||
|
||||
/**
|
||||
* 消息解码器
|
||||
*/
|
||||
private final ClientMessageDecoder decoder;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
|
||||
public ClientMessageCodecFactory() {
|
||||
encoder = new ClientMessageEncoder();
|
||||
decoder = new ClientMessageDecoder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new (or reusable) instance of ProtocolEncoder.
|
||||
*/
|
||||
|
||||
public ProtocolEncoder getEncoder(IoSession session) throws Exception {
|
||||
return encoder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new (or reusable) instance of ProtocolDecoder.
|
||||
*/
|
||||
public ProtocolDecoder getDecoder(IoSession session) throws Exception {
|
||||
return decoder;
|
||||
}
|
||||
|
@ -1,29 +1,40 @@
|
||||
/**
|
||||
* probject:cim-android-sdk
|
||||
* @version 2.1.0
|
||||
*
|
||||
* @author 3979434@qq.com
|
||||
*/
|
||||
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.sdk.android.filter;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
|
||||
import org.apache.mina.core.buffer.IoBuffer;
|
||||
import org.apache.mina.core.session.IoSession;
|
||||
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
|
||||
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.farsunset.cim.sdk.android.constant.CIMConstant;
|
||||
import com.farsunset.cim.sdk.android.model.HeartbeatRequest;
|
||||
import com.farsunset.cim.sdk.android.model.Message;
|
||||
import com.farsunset.cim.sdk.android.model.ReplyBody;
|
||||
import com.farsunset.cim.sdk.android.model.proto.MessageProto;
|
||||
import com.farsunset.cim.sdk.android.model.proto.ReplyBodyProto;
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
/**
|
||||
* 客户端消息解码
|
||||
*/
|
||||
@ -33,141 +44,100 @@ public class ClientMessageDecoder extends CumulativeProtocolDecoder {
|
||||
|
||||
|
||||
@Override
|
||||
public boolean doDecode(IoSession iosession, IoBuffer iobuffer,ProtocolDecoderOutput out) throws Exception {
|
||||
|
||||
boolean complete = false;
|
||||
IoBuffer tBuffer = IoBuffer.allocate(320).setAutoExpand(true);
|
||||
iobuffer.mark();
|
||||
|
||||
while (iobuffer.hasRemaining()) {
|
||||
byte b = iobuffer.get();
|
||||
/**
|
||||
* CIMConstant.MESSAGE_SEPARATE 为消息界限
|
||||
* 当一次收到多个消息时,以此分隔解析多个消息
|
||||
*/
|
||||
if (b == CIMConstant.MESSAGE_SEPARATE) {
|
||||
public boolean doDecode(IoSession iosession, IoBuffer iobuffer,
|
||||
ProtocolDecoderOutput out) throws Exception {
|
||||
|
||||
complete = true;
|
||||
break;
|
||||
} else {
|
||||
tBuffer.put(b);
|
||||
}
|
||||
}
|
||||
|
||||
if (complete) {
|
||||
tBuffer.flip();
|
||||
byte[] bytes = new byte[tBuffer.limit()];
|
||||
tBuffer.get(bytes);
|
||||
String message = new String(bytes, CIMConstant.UTF8);
|
||||
tBuffer.clear();
|
||||
|
||||
try
|
||||
{
|
||||
Object msg = mappingMessageObject(message);
|
||||
out.write(msg);
|
||||
}catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}else
|
||||
{
|
||||
iobuffer.reset();//如果消息没有接收完整,对buffer进行重置,下次继续读取
|
||||
}
|
||||
|
||||
return complete;
|
||||
}
|
||||
|
||||
private Object mappingMessageObject(String message) throws Exception {
|
||||
|
||||
|
||||
Log.i(TAG,message.toString());
|
||||
|
||||
if(CIMConstant.CMD_HEARTBEAT_REQUEST.equalsIgnoreCase(message))
|
||||
{
|
||||
return message;
|
||||
}
|
||||
|
||||
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||
Document doc = (Document) builder.parse(new ByteArrayInputStream(message.getBytes(CIMConstant.UTF8)));
|
||||
/**
|
||||
* 消息头3位
|
||||
*/
|
||||
if(iobuffer.remaining() < CIMConstant.DATA_HEADER_LENGTH){
|
||||
return false;
|
||||
}
|
||||
|
||||
iobuffer.mark();
|
||||
|
||||
byte conetnType = iobuffer.get();
|
||||
|
||||
byte lv =iobuffer.get();//int 低位
|
||||
byte hv =iobuffer.get();//int 高位
|
||||
|
||||
int conetnLength = getContentLength(lv,hv);
|
||||
|
||||
//如果消息体没有接收完整,则重置读取,等待下一次重新读取
|
||||
if(conetnLength > iobuffer.remaining()){
|
||||
iobuffer.reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
byte[] dataBytes = new byte[conetnLength];
|
||||
iobuffer.get(dataBytes, 0, conetnLength);
|
||||
|
||||
String name = doc.getDocumentElement().getTagName();
|
||||
if (name.equals("reply")) {
|
||||
ReplyBody reply = new ReplyBody();
|
||||
reply.setKey(doc.getElementsByTagName("key").item(0).getTextContent());
|
||||
reply.setCode(doc.getElementsByTagName("code").item(0).getTextContent());
|
||||
NodeList items = doc.getElementsByTagName("data").item(0).getChildNodes();
|
||||
for (int i = 0; i < items.getLength(); i++) {
|
||||
Node node = items.item(i);
|
||||
reply.put(node.getNodeName(), node.getTextContent());
|
||||
}
|
||||
return reply;
|
||||
}
|
||||
if (name.equals("message")) {
|
||||
|
||||
Message body = new Message();
|
||||
NodeList nodeList = doc.getElementsByTagName("message").item(0).getChildNodes();
|
||||
int count = nodeList.getLength();
|
||||
for(int i = 0;i < count; i++){
|
||||
Node node = nodeList.item(i);
|
||||
|
||||
if(node.getNodeName().equals("mid"))
|
||||
{
|
||||
body.setMid(node.getTextContent());
|
||||
}
|
||||
|
||||
if(node.getNodeName().equals("type"))
|
||||
{
|
||||
body.setType(node.getTextContent());
|
||||
}
|
||||
|
||||
if(node.getNodeName().equals("content"))
|
||||
{
|
||||
body.setContent(node.getTextContent());
|
||||
}
|
||||
|
||||
if(node.getNodeName().equals("file"))
|
||||
{
|
||||
body.setFile(node.getTextContent());
|
||||
}
|
||||
|
||||
if(node.getNodeName().equals("fileType"))
|
||||
{
|
||||
body.setFileType(node.getTextContent());
|
||||
}
|
||||
|
||||
if(node.getNodeName().equals("title"))
|
||||
{
|
||||
body.setTitle(node.getTextContent());
|
||||
}
|
||||
|
||||
if(node.getNodeName().equals("sender"))
|
||||
{
|
||||
body.setSender(node.getTextContent());
|
||||
}
|
||||
|
||||
if(node.getNodeName().equals("receiver"))
|
||||
{
|
||||
body.setReceiver(node.getTextContent());
|
||||
}
|
||||
|
||||
if(node.getNodeName().equals("format"))
|
||||
{
|
||||
body.setFormat(node.getTextContent());
|
||||
}
|
||||
|
||||
if(node.getNodeName().equals("timestamp"))
|
||||
{
|
||||
body.setTimestamp(Long.valueOf(node.getTextContent()));
|
||||
}
|
||||
}
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
return null;
|
||||
Object message = mappingMessageObject(dataBytes,conetnType);
|
||||
if(message!=null){
|
||||
out.write(message);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private Object mappingMessageObject(byte[] bytes,byte type) throws InvalidProtocolBufferException {
|
||||
|
||||
|
||||
|
||||
if(CIMConstant.ProtobufType.S_H_RQ == type)
|
||||
{
|
||||
HeartbeatRequest request = HeartbeatRequest.getInstance();
|
||||
Log.i(TAG,request.toString());
|
||||
return request;
|
||||
}
|
||||
|
||||
if(CIMConstant.ProtobufType.REPLYBODY == type)
|
||||
{
|
||||
ReplyBodyProto.Model bodyProto = ReplyBodyProto.Model.parseFrom(bytes);
|
||||
ReplyBody body = new ReplyBody();
|
||||
body.setKey(bodyProto.getKey());
|
||||
body.setTimestamp(bodyProto.getTimestamp());
|
||||
body.putAll(bodyProto.getDataMap());
|
||||
body.setCode(bodyProto.getCode());
|
||||
body.setMessage(bodyProto.getMessage());
|
||||
|
||||
Log.i(TAG,body.toString());
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
if(CIMConstant.ProtobufType.MESSAGE == type)
|
||||
{
|
||||
MessageProto.Model bodyProto = MessageProto.Model.parseFrom(bytes);
|
||||
Message message = new Message();
|
||||
message.setMid(bodyProto.getMid());
|
||||
message.setAction(bodyProto.getAction());
|
||||
message.setContent(bodyProto.getContent());
|
||||
message.setSender(bodyProto.getSender());
|
||||
message.setReceiver(bodyProto.getReceiver());
|
||||
message.setTitle(bodyProto.getTitle());
|
||||
message.setExtra(bodyProto.getExtra());
|
||||
message.setTimestamp(bodyProto.getTimestamp());
|
||||
message.setFormat(bodyProto.getFormat());
|
||||
|
||||
Log.i(TAG,message.toString());
|
||||
return message;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析消息体长度
|
||||
* @param type
|
||||
* @param length
|
||||
* @return
|
||||
*/
|
||||
private int getContentLength(byte lv,byte hv){
|
||||
int l = (lv & 0xff);
|
||||
int h = (hv & 0xff);
|
||||
return (l| (h <<= 8));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,40 +1,73 @@
|
||||
/**
|
||||
* probject:cim-android-sdk
|
||||
* @version 2.1.0
|
||||
*
|
||||
* @author 3979434@qq.com
|
||||
*/
|
||||
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.sdk.android.filter;
|
||||
|
||||
|
||||
|
||||
import org.apache.mina.core.buffer.IoBuffer;
|
||||
import org.apache.mina.core.session.IoSession;
|
||||
import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
|
||||
import org.apache.mina.filter.codec.ProtocolEncoderOutput;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.farsunset.cim.sdk.android.constant.CIMConstant;
|
||||
import com.farsunset.cim.sdk.android.model.Protobufable;
|
||||
/**
|
||||
* 客户端消息发送前进行编码,可在此加密消息
|
||||
* 客户端消息发送前进行编码
|
||||
*/
|
||||
public class ClientMessageEncoder extends ProtocolEncoderAdapter {
|
||||
|
||||
final static String TAG = ClientMessageEncoder.class.getSimpleName();
|
||||
@Override
|
||||
public void encode(IoSession iosession, Object message, ProtocolEncoderOutput out) throws Exception {
|
||||
public void encode(IoSession iosession, Object object, ProtocolEncoderOutput out) throws Exception {
|
||||
|
||||
IoBuffer buff = IoBuffer.allocate(320).setAutoExpand(true);
|
||||
buff.put(message.toString().getBytes(CIMConstant.UTF8));
|
||||
buff.put(CIMConstant.MESSAGE_SEPARATE);
|
||||
buff.flip();
|
||||
out.write(buff);
|
||||
//打印出收到的消息
|
||||
Log.i(TAG,message.toString());
|
||||
if(object instanceof Protobufable){
|
||||
|
||||
Protobufable data = (Protobufable) object;
|
||||
byte[] byteArray = data.getByteArray();
|
||||
|
||||
IoBuffer buff = IoBuffer.allocate(byteArray.length + CIMConstant.DATA_HEADER_LENGTH).setAutoExpand(true);
|
||||
|
||||
buff.put(createHeader(data.getType(),byteArray.length));
|
||||
buff.put(byteArray);
|
||||
|
||||
buff.flip();
|
||||
out.write(buff);
|
||||
//打印出收到的消息
|
||||
Log.i(TAG,data.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 消息体最大为65535
|
||||
* @param type
|
||||
* @param length
|
||||
* @return
|
||||
*/
|
||||
private byte[] createHeader(byte type,int length){
|
||||
byte[] header = new byte[CIMConstant.DATA_HEADER_LENGTH];
|
||||
header[0] = type;
|
||||
header[1] = (byte) (length & 0xff);
|
||||
header[2] = (byte) ((length >> 8) & 0xff);
|
||||
return header;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,62 @@
|
||||
/**
|
||||
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.sdk.android.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.farsunset.cim.sdk.android.constant.CIMConstant;
|
||||
/**
|
||||
* 服务端心跳请求
|
||||
*
|
||||
*/
|
||||
public class HeartbeatRequest implements Serializable,Protobufable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String TAG = "SERVER_HEARTBEAT_REQUEST";
|
||||
private static final String CMD_HEARTBEAT_RESPONSE = "SR";
|
||||
|
||||
private static HeartbeatRequest object = new HeartbeatRequest();
|
||||
|
||||
private HeartbeatRequest(){
|
||||
|
||||
}
|
||||
|
||||
public static HeartbeatRequest getInstance() {
|
||||
return object;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getByteArray() {
|
||||
return CMD_HEARTBEAT_RESPONSE.getBytes();
|
||||
}
|
||||
|
||||
public String toString(){
|
||||
return TAG;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public byte getType() {
|
||||
return CIMConstant.ProtobufType.S_H_RQ;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
/**
|
||||
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.sdk.android.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.farsunset.cim.sdk.android.constant.CIMConstant;
|
||||
/**
|
||||
* 客户端心跳响应
|
||||
*/
|
||||
public class HeartbeatResponse implements Serializable,Protobufable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String TAG = "CLIENT_HEARTBEAT_RESPONSE";
|
||||
private static final String CMD_HEARTBEAT_RESPONSE = "CR";
|
||||
|
||||
private static HeartbeatResponse object = new HeartbeatResponse();
|
||||
|
||||
private HeartbeatResponse(){
|
||||
|
||||
}
|
||||
|
||||
public static HeartbeatResponse getInstance() {
|
||||
return object;
|
||||
}
|
||||
@Override
|
||||
public byte[] getByteArray() {
|
||||
return CMD_HEARTBEAT_RESPONSE.getBytes();
|
||||
}
|
||||
|
||||
public String toString(){
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getType() {
|
||||
return CIMConstant.ProtobufType.C_H_RS;
|
||||
}
|
||||
|
||||
}
|
@ -1,12 +1,28 @@
|
||||
/**
|
||||
* probject:cim-android-sdk
|
||||
* @version 2.1.0
|
||||
*
|
||||
* @author 3979434@qq.com
|
||||
*/
|
||||
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.sdk.android.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 消息对象
|
||||
*/
|
||||
@ -24,13 +40,13 @@ public class Message implements Serializable {
|
||||
/**
|
||||
* 消息类型,用户自定义消息类别
|
||||
*/
|
||||
private String type;
|
||||
private String action;
|
||||
/**
|
||||
* 消息标题
|
||||
*/
|
||||
private String title;
|
||||
/**
|
||||
* 消息类容,于type 组合为任何类型消息,content 根据 format 可表示为 text,json ,xml数据格式
|
||||
* 消息类容,于action 组合为任何类型消息,content 根据 format 可表示为 text,json ,xml数据格式
|
||||
*/
|
||||
private String content;
|
||||
|
||||
@ -43,21 +59,18 @@ public class Message implements Serializable {
|
||||
*/
|
||||
private String receiver;
|
||||
|
||||
/**
|
||||
* 文件 url
|
||||
*/
|
||||
private String file;
|
||||
/**
|
||||
* 文件类型
|
||||
*/
|
||||
private String fileType;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* content 内容格式
|
||||
*/
|
||||
private String format = "txt";
|
||||
private String format;
|
||||
|
||||
/**
|
||||
* 附加内容 内容
|
||||
*/
|
||||
private String extra;
|
||||
|
||||
|
||||
private long timestamp;
|
||||
|
||||
|
||||
@ -73,14 +86,14 @@ public class Message implements Serializable {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
public String getAction() {
|
||||
return action;
|
||||
}
|
||||
public void setAction(String action) {
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
@ -113,22 +126,7 @@ public class Message implements Serializable {
|
||||
this.receiver = receiver;
|
||||
}
|
||||
|
||||
public String getFile() {
|
||||
return file;
|
||||
}
|
||||
|
||||
public void setFile(String file) {
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
public String getFileType() {
|
||||
return fileType;
|
||||
}
|
||||
|
||||
public void setFileType(String fileType) {
|
||||
this.fileType = fileType;
|
||||
}
|
||||
|
||||
|
||||
public String getFormat() {
|
||||
return format;
|
||||
}
|
||||
@ -137,56 +135,30 @@ public class Message implements Serializable {
|
||||
this.format = format;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String getExtra() {
|
||||
return extra;
|
||||
}
|
||||
public void setExtra(String extra) {
|
||||
this.extra = extra;
|
||||
}
|
||||
public String toString() {
|
||||
|
||||
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
||||
buffer.append("<message>");
|
||||
buffer.append("<mid>").append(mid).append("</mid>");
|
||||
|
||||
if (isNotEmpty(type)) {
|
||||
buffer.append("<type>").append(type).append("</type>");
|
||||
}
|
||||
|
||||
if (isNotEmpty(title)) {
|
||||
buffer.append("<title>").append(title).append("</title>");
|
||||
}
|
||||
if (isNotEmpty(content)) {
|
||||
buffer.append("<content><![CDATA[").append(content).append("]]></content>");
|
||||
}
|
||||
|
||||
if (isNotEmpty(file)) {
|
||||
buffer.append("<file>").append(file).append("</file>");
|
||||
}
|
||||
|
||||
if (isNotEmpty(fileType)) {
|
||||
buffer.append("<fileType>").append(fileType).append("</fileType>");
|
||||
}
|
||||
|
||||
if (isNotEmpty(sender)) {
|
||||
buffer.append("<sender>").append(sender).append("</sender>");
|
||||
}
|
||||
|
||||
if (isNotEmpty(receiver)) {
|
||||
buffer.append("<receiver>").append(receiver).append("</receiver>");
|
||||
}
|
||||
|
||||
if (isNotEmpty(format)) {
|
||||
buffer.append("<format>").append(format).append("</format>");
|
||||
}
|
||||
|
||||
if (timestamp > 0) {
|
||||
buffer.append("<timestamp>").append(timestamp).append("</timestamp>");
|
||||
}
|
||||
|
||||
buffer.append("</message>");
|
||||
buffer.append("#Message#").append("\n");
|
||||
buffer.append("mid:").append(mid).append("\n");
|
||||
buffer.append("action:").append(action).append("\n");
|
||||
buffer.append("title:").append(title).append("\n");
|
||||
buffer.append("content:").append(content).append("\n");
|
||||
buffer.append("extra:").append(extra).append("\n");
|
||||
buffer.append("sender:").append(sender).append("\n");
|
||||
buffer.append("receiver:").append(receiver).append("\n");
|
||||
buffer.append("format:").append(format).append("\n");
|
||||
buffer.append("timestamp:").append(timestamp);
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public String toXmlString() {
|
||||
|
||||
return toString();
|
||||
}
|
||||
|
||||
|
||||
public String getMid() {
|
||||
return mid;
|
||||
@ -197,8 +169,8 @@ public class Message implements Serializable {
|
||||
}
|
||||
|
||||
public boolean isNotEmpty(String txt) {
|
||||
return txt != null && !txt.isEmpty();
|
||||
return txt != null && txt.trim().length()!=0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.sdk.android.model;
|
||||
/**
|
||||
* 需要向另一端发送的结构体
|
||||
*/
|
||||
public interface Protobufable {
|
||||
|
||||
byte[] getByteArray();
|
||||
|
||||
byte getType();
|
||||
}
|
@ -1,13 +1,30 @@
|
||||
/**
|
||||
* probject:cim-android-sdk
|
||||
* @version 2.1.0
|
||||
*
|
||||
* @author 3979434@qq.com
|
||||
*/
|
||||
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.sdk.android.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
/**
|
||||
* 请求应答对象
|
||||
*
|
||||
@ -64,7 +81,9 @@ public class ReplyBody implements Serializable {
|
||||
}
|
||||
|
||||
public void put(String k, String v) {
|
||||
data.put(k, v);
|
||||
if(v!=null && k!=null){
|
||||
data.put(k, v);
|
||||
}
|
||||
}
|
||||
|
||||
public String get(String k) {
|
||||
@ -83,8 +102,12 @@ public class ReplyBody implements Serializable {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public HashMap<String, String> getData() {
|
||||
return data;
|
||||
public void putAll(Map<String, String> map) {
|
||||
data.putAll(map);
|
||||
}
|
||||
|
||||
public Set<String> getKeySet() {
|
||||
return data.keySet();
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
@ -98,27 +121,22 @@ public class ReplyBody implements Serializable {
|
||||
|
||||
public String toString()
|
||||
{
|
||||
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
||||
buffer.append("<reply>");
|
||||
buffer.append("<key>").append(this.getKey()).append("</key>");
|
||||
buffer.append("<timestamp>").append(timestamp).append("</timestamp>");
|
||||
buffer.append("<code>").append(code).append("</code>");
|
||||
buffer.append("<data>");
|
||||
for(String key:this.getData().keySet())
|
||||
{
|
||||
buffer.append("<"+key+">").append(this.get(key)).append("</"+key+">");
|
||||
buffer.append("#ReplyBody#").append("\n");
|
||||
buffer.append("key:").append(this.getKey()).append("\n");
|
||||
buffer.append("timestamp:").append(timestamp).append("\n");
|
||||
buffer.append("code:").append(code).append("\n");
|
||||
|
||||
if(!data.isEmpty()){
|
||||
buffer.append("data{").append("\n");
|
||||
for(String key:getKeySet())
|
||||
{
|
||||
buffer.append(key).append(":").append(this.get(key)).append("\n");
|
||||
}
|
||||
buffer.append("}");
|
||||
}
|
||||
buffer.append("</data>");
|
||||
buffer.append("</reply>");
|
||||
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
|
||||
public String toXmlString()
|
||||
{
|
||||
|
||||
return toString();
|
||||
}
|
||||
}
|
||||
|
@ -1,30 +1,48 @@
|
||||
/**
|
||||
* probject:cim-android-sdk
|
||||
* @version 2.1.0
|
||||
*
|
||||
* @author 3979434@qq.com
|
||||
*/
|
||||
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.sdk.android.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.farsunset.cim.sdk.android.constant.CIMConstant;
|
||||
import com.farsunset.cim.sdk.android.model.proto.SentBodyProto;
|
||||
/**
|
||||
* java |android 客户端请求结构
|
||||
*
|
||||
*/
|
||||
public class SentBody implements Serializable {
|
||||
public class SentBody implements Serializable,Protobufable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String key;
|
||||
|
||||
private HashMap<String, String> data;
|
||||
private HashMap<String, String> data = new HashMap<String, String>();;
|
||||
|
||||
private long timestamp;
|
||||
|
||||
public SentBody() {
|
||||
|
||||
data = new HashMap<String, String>();
|
||||
timestamp = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
@ -49,36 +67,54 @@ public class SentBody implements Serializable {
|
||||
}
|
||||
|
||||
public void put(String k, String v) {
|
||||
data.put(k, v);
|
||||
if(v!=null && k!=null){
|
||||
data.put(k, v);
|
||||
}
|
||||
}
|
||||
public void putAll(Map<String, String> map) {
|
||||
data.putAll(map);
|
||||
}
|
||||
|
||||
public Set<String> getKeySet() {
|
||||
return data.keySet();
|
||||
}
|
||||
|
||||
|
||||
public void remove(String k) {
|
||||
data.remove(k);
|
||||
}
|
||||
|
||||
public HashMap<String, String> getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
||||
buffer.append("<sent>");
|
||||
buffer.append("<key>").append(key).append("</key>");
|
||||
buffer.append("<timestamp>").append(timestamp).append("</timestamp>");
|
||||
buffer.append("<data>");
|
||||
for (String key : data.keySet()) {
|
||||
buffer.append("<" + key + ">").append(data.get(key)).append(
|
||||
"</" + key + ">");
|
||||
buffer.append("#SentBody#").append("\n");;
|
||||
buffer.append("key:").append(key).append("\n");
|
||||
buffer.append("timestamp:").append(timestamp).append("\n");
|
||||
if(!data.isEmpty()){
|
||||
buffer.append("data{").append("\n");
|
||||
for(String key:getKeySet())
|
||||
{
|
||||
buffer.append(key).append(":").append(this.get(key)).append("\n");
|
||||
}
|
||||
buffer.append("}");
|
||||
}
|
||||
buffer.append("</data>");
|
||||
buffer.append("</sent>");
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public String toXmlString() {
|
||||
|
||||
return toString();
|
||||
|
||||
@Override
|
||||
public byte[] getByteArray() {
|
||||
SentBodyProto.Model.Builder builder = SentBodyProto.Model.newBuilder();
|
||||
builder.setKey(key);
|
||||
builder.setTimestamp(timestamp);
|
||||
if(!data.isEmpty()){
|
||||
builder.putAllData(data);
|
||||
}
|
||||
return builder.build().toByteArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getType() {
|
||||
return CIMConstant.ProtobufType.SENTBODY;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,15 @@
|
||||
syntax = "proto3";
|
||||
package com.farsunset.cim.sdk.android.model.proto;
|
||||
option java_outer_classname="MessageProto";
|
||||
message Model {
|
||||
string mid = 1;
|
||||
string action = 2;
|
||||
string content = 3;
|
||||
string sender = 4;
|
||||
string receiver = 5;
|
||||
string extra = 6;
|
||||
string title = 7;
|
||||
string format = 8;
|
||||
int64 timestamp = 9;
|
||||
}
|
||||
|
@ -0,0 +1,13 @@
|
||||
syntax = "proto3";
|
||||
package com.farsunset.cim.sdk.android.model.proto;
|
||||
option java_outer_classname="ReplyBodyProto";
|
||||
|
||||
message Model {
|
||||
string key = 1;
|
||||
string code = 2;
|
||||
string message = 3;
|
||||
int64 timestamp =4;
|
||||
map<string,string> data =5;
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,11 @@
|
||||
syntax = "proto3";
|
||||
package com.farsunset.cim.sdk.android.model.proto;
|
||||
option java_outer_classname="SentBodyProto";
|
||||
|
||||
message Model {
|
||||
string key = 1;
|
||||
int64 timestamp =2;
|
||||
map<string,string> data =3;
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,967 @@
|
||||
/**
|
||||
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.cim.sdk.android.model.proto;
|
||||
|
||||
public final class SentBodyProto {
|
||||
private SentBodyProto() {}
|
||||
public static void registerAllExtensions(
|
||||
com.google.protobuf.ExtensionRegistryLite registry) {
|
||||
}
|
||||
|
||||
public static void registerAllExtensions(
|
||||
com.google.protobuf.ExtensionRegistry registry) {
|
||||
registerAllExtensions(
|
||||
(com.google.protobuf.ExtensionRegistryLite) registry);
|
||||
}
|
||||
public interface ModelOrBuilder extends
|
||||
// @@protoc_insertion_point(interface_extends:com.farsunset.cim.sdk.android.model.proto.Model)
|
||||
com.google.protobuf.MessageOrBuilder {
|
||||
|
||||
/**
|
||||
* <code>string key = 1;</code>
|
||||
*/
|
||||
java.lang.String getKey();
|
||||
/**
|
||||
* <code>string key = 1;</code>
|
||||
*/
|
||||
com.google.protobuf.ByteString
|
||||
getKeyBytes();
|
||||
|
||||
/**
|
||||
* <code>int64 timestamp = 2;</code>
|
||||
*/
|
||||
long getTimestamp();
|
||||
|
||||
/**
|
||||
* <code>map<string, string> data = 3;</code>
|
||||
*/
|
||||
int getDataCount();
|
||||
/**
|
||||
* <code>map<string, string> data = 3;</code>
|
||||
*/
|
||||
boolean containsData(
|
||||
java.lang.String key);
|
||||
/**
|
||||
* Use {@link #getDataMap()} instead.
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
java.util.Map<java.lang.String, java.lang.String>
|
||||
getData();
|
||||
/**
|
||||
* <code>map<string, string> data = 3;</code>
|
||||
*/
|
||||
java.util.Map<java.lang.String, java.lang.String>
|
||||
getDataMap();
|
||||
/**
|
||||
* <code>map<string, string> data = 3;</code>
|
||||
*/
|
||||
|
||||
java.lang.String getDataOrDefault(
|
||||
java.lang.String key,
|
||||
java.lang.String defaultValue);
|
||||
/**
|
||||
* <code>map<string, string> data = 3;</code>
|
||||
*/
|
||||
|
||||
java.lang.String getDataOrThrow(
|
||||
java.lang.String key);
|
||||
}
|
||||
/**
|
||||
* Protobuf type {@code com.farsunset.cim.sdk.android.model.proto.Model}
|
||||
*/
|
||||
public static final class Model extends
|
||||
com.google.protobuf.GeneratedMessageV3 implements
|
||||
// @@protoc_insertion_point(message_implements:com.farsunset.cim.sdk.android.model.proto.Model)
|
||||
ModelOrBuilder {
|
||||
// Use Model.newBuilder() to construct.
|
||||
private Model(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
|
||||
super(builder);
|
||||
}
|
||||
private Model() {
|
||||
key_ = "";
|
||||
timestamp_ = 0L;
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
public final com.google.protobuf.UnknownFieldSet
|
||||
getUnknownFields() {
|
||||
return com.google.protobuf.UnknownFieldSet.getDefaultInstance();
|
||||
}
|
||||
private Model(
|
||||
com.google.protobuf.CodedInputStream input,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
this();
|
||||
int mutable_bitField0_ = 0;
|
||||
try {
|
||||
boolean done = false;
|
||||
while (!done) {
|
||||
int tag = input.readTag();
|
||||
switch (tag) {
|
||||
case 0:
|
||||
done = true;
|
||||
break;
|
||||
default: {
|
||||
if (!input.skipField(tag)) {
|
||||
done = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 10: {
|
||||
java.lang.String s = input.readStringRequireUtf8();
|
||||
|
||||
key_ = s;
|
||||
break;
|
||||
}
|
||||
case 16: {
|
||||
|
||||
timestamp_ = input.readInt64();
|
||||
break;
|
||||
}
|
||||
case 26: {
|
||||
if (!((mutable_bitField0_ & 0x00000004) == 0x00000004)) {
|
||||
data_ = com.google.protobuf.MapField.newMapField(
|
||||
DataDefaultEntryHolder.defaultEntry);
|
||||
mutable_bitField0_ |= 0x00000004;
|
||||
}
|
||||
com.google.protobuf.MapEntry<java.lang.String, java.lang.String>
|
||||
data__ = input.readMessage(
|
||||
DataDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry);
|
||||
data_.getMutableMap().put(
|
||||
data__.getKey(), data__.getValue());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
|
||||
throw e.setUnfinishedMessage(this);
|
||||
} catch (java.io.IOException e) {
|
||||
throw new com.google.protobuf.InvalidProtocolBufferException(
|
||||
e).setUnfinishedMessage(this);
|
||||
} finally {
|
||||
makeExtensionsImmutable();
|
||||
}
|
||||
}
|
||||
public static final com.google.protobuf.Descriptors.Descriptor
|
||||
getDescriptor() {
|
||||
return com.farsunset.cim.sdk.android.model.proto.SentBodyProto.internal_static_com_farsunset_cim_sdk_android_model_proto_Model_descriptor;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"rawtypes"})
|
||||
protected com.google.protobuf.MapField internalGetMapField(
|
||||
int number) {
|
||||
switch (number) {
|
||||
case 3:
|
||||
return internalGetData();
|
||||
default:
|
||||
throw new RuntimeException(
|
||||
"Invalid map field number: " + number);
|
||||
}
|
||||
}
|
||||
protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
|
||||
internalGetFieldAccessorTable() {
|
||||
return com.farsunset.cim.sdk.android.model.proto.SentBodyProto.internal_static_com_farsunset_cim_sdk_android_model_proto_Model_fieldAccessorTable
|
||||
.ensureFieldAccessorsInitialized(
|
||||
com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model.class, com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model.Builder.class);
|
||||
}
|
||||
|
||||
private int bitField0_;
|
||||
public static final int KEY_FIELD_NUMBER = 1;
|
||||
private volatile java.lang.Object key_;
|
||||
/**
|
||||
* <code>string key = 1;</code>
|
||||
*/
|
||||
public java.lang.String getKey() {
|
||||
java.lang.Object ref = key_;
|
||||
if (ref instanceof java.lang.String) {
|
||||
return (java.lang.String) ref;
|
||||
} else {
|
||||
com.google.protobuf.ByteString bs =
|
||||
(com.google.protobuf.ByteString) ref;
|
||||
java.lang.String s = bs.toStringUtf8();
|
||||
key_ = s;
|
||||
return s;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* <code>string key = 1;</code>
|
||||
*/
|
||||
public com.google.protobuf.ByteString
|
||||
getKeyBytes() {
|
||||
java.lang.Object ref = key_;
|
||||
if (ref instanceof java.lang.String) {
|
||||
com.google.protobuf.ByteString b =
|
||||
com.google.protobuf.ByteString.copyFromUtf8(
|
||||
(java.lang.String) ref);
|
||||
key_ = b;
|
||||
return b;
|
||||
} else {
|
||||
return (com.google.protobuf.ByteString) ref;
|
||||
}
|
||||
}
|
||||
|
||||
public static final int TIMESTAMP_FIELD_NUMBER = 2;
|
||||
private long timestamp_;
|
||||
/**
|
||||
* <code>int64 timestamp = 2;</code>
|
||||
*/
|
||||
public long getTimestamp() {
|
||||
return timestamp_;
|
||||
}
|
||||
|
||||
public static final int DATA_FIELD_NUMBER = 3;
|
||||
private static final class DataDefaultEntryHolder {
|
||||
static final com.google.protobuf.MapEntry<
|
||||
java.lang.String, java.lang.String> defaultEntry =
|
||||
com.google.protobuf.MapEntry
|
||||
.<java.lang.String, java.lang.String>newDefaultInstance(
|
||||
com.farsunset.cim.sdk.android.model.proto.SentBodyProto.internal_static_com_farsunset_cim_sdk_android_model_proto_Model_DataEntry_descriptor,
|
||||
com.google.protobuf.WireFormat.FieldType.STRING,
|
||||
"",
|
||||
com.google.protobuf.WireFormat.FieldType.STRING,
|
||||
"");
|
||||
}
|
||||
private com.google.protobuf.MapField<
|
||||
java.lang.String, java.lang.String> data_;
|
||||
private com.google.protobuf.MapField<java.lang.String, java.lang.String>
|
||||
internalGetData() {
|
||||
if (data_ == null) {
|
||||
return com.google.protobuf.MapField.emptyMapField(
|
||||
DataDefaultEntryHolder.defaultEntry);
|
||||
}
|
||||
return data_;
|
||||
}
|
||||
|
||||
public int getDataCount() {
|
||||
return internalGetData().getMap().size();
|
||||
}
|
||||
/**
|
||||
* <code>map<string, string> data = 3;</code>
|
||||
*/
|
||||
|
||||
public boolean containsData(
|
||||
java.lang.String key) {
|
||||
if (key == null) { throw new java.lang.NullPointerException(); }
|
||||
return internalGetData().getMap().containsKey(key);
|
||||
}
|
||||
/**
|
||||
* Use {@link #getDataMap()} instead.
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
public java.util.Map<java.lang.String, java.lang.String> getData() {
|
||||
return getDataMap();
|
||||
}
|
||||
/**
|
||||
* <code>map<string, string> data = 3;</code>
|
||||
*/
|
||||
|
||||
public java.util.Map<java.lang.String, java.lang.String> getDataMap() {
|
||||
return internalGetData().getMap();
|
||||
}
|
||||
/**
|
||||
* <code>map<string, string> data = 3;</code>
|
||||
*/
|
||||
|
||||
public java.lang.String getDataOrDefault(
|
||||
java.lang.String key,
|
||||
java.lang.String defaultValue) {
|
||||
if (key == null) { throw new java.lang.NullPointerException(); }
|
||||
java.util.Map<java.lang.String, java.lang.String> map =
|
||||
internalGetData().getMap();
|
||||
return map.containsKey(key) ? map.get(key) : defaultValue;
|
||||
}
|
||||
/**
|
||||
* <code>map<string, string> data = 3;</code>
|
||||
*/
|
||||
|
||||
public java.lang.String getDataOrThrow(
|
||||
java.lang.String key) {
|
||||
if (key == null) { throw new java.lang.NullPointerException(); }
|
||||
java.util.Map<java.lang.String, java.lang.String> map =
|
||||
internalGetData().getMap();
|
||||
if (!map.containsKey(key)) {
|
||||
throw new java.lang.IllegalArgumentException();
|
||||
}
|
||||
return map.get(key);
|
||||
}
|
||||
|
||||
private byte memoizedIsInitialized = -1;
|
||||
public final boolean isInitialized() {
|
||||
byte isInitialized = memoizedIsInitialized;
|
||||
if (isInitialized == 1) return true;
|
||||
if (isInitialized == 0) return false;
|
||||
|
||||
memoizedIsInitialized = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void writeTo(com.google.protobuf.CodedOutputStream output)
|
||||
throws java.io.IOException {
|
||||
if (!getKeyBytes().isEmpty()) {
|
||||
com.google.protobuf.GeneratedMessageV3.writeString(output, 1, key_);
|
||||
}
|
||||
if (timestamp_ != 0L) {
|
||||
output.writeInt64(2, timestamp_);
|
||||
}
|
||||
com.google.protobuf.GeneratedMessageV3
|
||||
.serializeStringMapTo(
|
||||
output,
|
||||
internalGetData(),
|
||||
DataDefaultEntryHolder.defaultEntry,
|
||||
3);
|
||||
}
|
||||
|
||||
public int getSerializedSize() {
|
||||
int size = memoizedSize;
|
||||
if (size != -1) return size;
|
||||
|
||||
size = 0;
|
||||
if (!getKeyBytes().isEmpty()) {
|
||||
size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, key_);
|
||||
}
|
||||
if (timestamp_ != 0L) {
|
||||
size += com.google.protobuf.CodedOutputStream
|
||||
.computeInt64Size(2, timestamp_);
|
||||
}
|
||||
for (java.util.Map.Entry<java.lang.String, java.lang.String> entry
|
||||
: internalGetData().getMap().entrySet()) {
|
||||
com.google.protobuf.MapEntry<java.lang.String, java.lang.String>
|
||||
data__ = DataDefaultEntryHolder.defaultEntry.newBuilderForType()
|
||||
.setKey(entry.getKey())
|
||||
.setValue(entry.getValue())
|
||||
.build();
|
||||
size += com.google.protobuf.CodedOutputStream
|
||||
.computeMessageSize(3, data__);
|
||||
}
|
||||
memoizedSize = size;
|
||||
return size;
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 0L;
|
||||
@java.lang.Override
|
||||
public boolean equals(final java.lang.Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model)) {
|
||||
return super.equals(obj);
|
||||
}
|
||||
com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model other = (com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model) obj;
|
||||
|
||||
boolean result = true;
|
||||
result = result && getKey()
|
||||
.equals(other.getKey());
|
||||
result = result && (getTimestamp()
|
||||
== other.getTimestamp());
|
||||
result = result && internalGetData().equals(
|
||||
other.internalGetData());
|
||||
return result;
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
public int hashCode() {
|
||||
if (memoizedHashCode != 0) {
|
||||
return memoizedHashCode;
|
||||
}
|
||||
int hash = 41;
|
||||
hash = (19 * hash) + getDescriptor().hashCode();
|
||||
hash = (37 * hash) + KEY_FIELD_NUMBER;
|
||||
hash = (53 * hash) + getKey().hashCode();
|
||||
hash = (37 * hash) + TIMESTAMP_FIELD_NUMBER;
|
||||
hash = (53 * hash) + com.google.protobuf.Internal.hashLong(
|
||||
getTimestamp());
|
||||
if (!internalGetData().getMap().isEmpty()) {
|
||||
hash = (37 * hash) + DATA_FIELD_NUMBER;
|
||||
hash = (53 * hash) + internalGetData().hashCode();
|
||||
}
|
||||
hash = (29 * hash) + unknownFields.hashCode();
|
||||
memoizedHashCode = hash;
|
||||
return hash;
|
||||
}
|
||||
|
||||
public static com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model parseFrom(
|
||||
com.google.protobuf.ByteString data)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
return PARSER.parseFrom(data);
|
||||
}
|
||||
public static com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model parseFrom(
|
||||
com.google.protobuf.ByteString data,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
return PARSER.parseFrom(data, extensionRegistry);
|
||||
}
|
||||
public static com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model parseFrom(byte[] data)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
return PARSER.parseFrom(data);
|
||||
}
|
||||
public static com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model parseFrom(
|
||||
byte[] data,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
return PARSER.parseFrom(data, extensionRegistry);
|
||||
}
|
||||
public static com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model parseFrom(java.io.InputStream input)
|
||||
throws java.io.IOException {
|
||||
return com.google.protobuf.GeneratedMessageV3
|
||||
.parseWithIOException(PARSER, input);
|
||||
}
|
||||
public static com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model parseFrom(
|
||||
java.io.InputStream input,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws java.io.IOException {
|
||||
return com.google.protobuf.GeneratedMessageV3
|
||||
.parseWithIOException(PARSER, input, extensionRegistry);
|
||||
}
|
||||
public static com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model parseDelimitedFrom(java.io.InputStream input)
|
||||
throws java.io.IOException {
|
||||
return com.google.protobuf.GeneratedMessageV3
|
||||
.parseDelimitedWithIOException(PARSER, input);
|
||||
}
|
||||
public static com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model parseDelimitedFrom(
|
||||
java.io.InputStream input,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws java.io.IOException {
|
||||
return com.google.protobuf.GeneratedMessageV3
|
||||
.parseDelimitedWithIOException(PARSER, input, extensionRegistry);
|
||||
}
|
||||
public static com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model parseFrom(
|
||||
com.google.protobuf.CodedInputStream input)
|
||||
throws java.io.IOException {
|
||||
return com.google.protobuf.GeneratedMessageV3
|
||||
.parseWithIOException(PARSER, input);
|
||||
}
|
||||
public static com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model parseFrom(
|
||||
com.google.protobuf.CodedInputStream input,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws java.io.IOException {
|
||||
return com.google.protobuf.GeneratedMessageV3
|
||||
.parseWithIOException(PARSER, input, extensionRegistry);
|
||||
}
|
||||
|
||||
public Builder newBuilderForType() { return newBuilder(); }
|
||||
public static Builder newBuilder() {
|
||||
return DEFAULT_INSTANCE.toBuilder();
|
||||
}
|
||||
public static Builder newBuilder(com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model prototype) {
|
||||
return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
|
||||
}
|
||||
public Builder toBuilder() {
|
||||
return this == DEFAULT_INSTANCE
|
||||
? new Builder() : new Builder().mergeFrom(this);
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
protected Builder newBuilderForType(
|
||||
com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
|
||||
Builder builder = new Builder(parent);
|
||||
return builder;
|
||||
}
|
||||
/**
|
||||
* Protobuf type {@code com.farsunset.cim.sdk.android.model.proto.Model}
|
||||
*/
|
||||
public static final class Builder extends
|
||||
com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
|
||||
// @@protoc_insertion_point(builder_implements:com.farsunset.cim.sdk.android.model.proto.Model)
|
||||
com.farsunset.cim.sdk.android.model.proto.SentBodyProto.ModelOrBuilder {
|
||||
public static final com.google.protobuf.Descriptors.Descriptor
|
||||
getDescriptor() {
|
||||
return com.farsunset.cim.sdk.android.model.proto.SentBodyProto.internal_static_com_farsunset_cim_sdk_android_model_proto_Model_descriptor;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"rawtypes"})
|
||||
protected com.google.protobuf.MapField internalGetMapField(
|
||||
int number) {
|
||||
switch (number) {
|
||||
case 3:
|
||||
return internalGetData();
|
||||
default:
|
||||
throw new RuntimeException(
|
||||
"Invalid map field number: " + number);
|
||||
}
|
||||
}
|
||||
@SuppressWarnings({"rawtypes"})
|
||||
protected com.google.protobuf.MapField internalGetMutableMapField(
|
||||
int number) {
|
||||
switch (number) {
|
||||
case 3:
|
||||
return internalGetMutableData();
|
||||
default:
|
||||
throw new RuntimeException(
|
||||
"Invalid map field number: " + number);
|
||||
}
|
||||
}
|
||||
protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
|
||||
internalGetFieldAccessorTable() {
|
||||
return com.farsunset.cim.sdk.android.model.proto.SentBodyProto.internal_static_com_farsunset_cim_sdk_android_model_proto_Model_fieldAccessorTable
|
||||
.ensureFieldAccessorsInitialized(
|
||||
com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model.class, com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model.Builder.class);
|
||||
}
|
||||
|
||||
// Construct using com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model.newBuilder()
|
||||
private Builder() {
|
||||
maybeForceBuilderInitialization();
|
||||
}
|
||||
|
||||
private Builder(
|
||||
com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
|
||||
super(parent);
|
||||
maybeForceBuilderInitialization();
|
||||
}
|
||||
private void maybeForceBuilderInitialization() {
|
||||
if (com.google.protobuf.GeneratedMessageV3
|
||||
.alwaysUseFieldBuilders) {
|
||||
}
|
||||
}
|
||||
public Builder clear() {
|
||||
super.clear();
|
||||
key_ = "";
|
||||
|
||||
timestamp_ = 0L;
|
||||
|
||||
internalGetMutableData().clear();
|
||||
return this;
|
||||
}
|
||||
|
||||
public com.google.protobuf.Descriptors.Descriptor
|
||||
getDescriptorForType() {
|
||||
return com.farsunset.cim.sdk.android.model.proto.SentBodyProto.internal_static_com_farsunset_cim_sdk_android_model_proto_Model_descriptor;
|
||||
}
|
||||
|
||||
public com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model getDefaultInstanceForType() {
|
||||
return com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model.getDefaultInstance();
|
||||
}
|
||||
|
||||
public com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model build() {
|
||||
com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model result = buildPartial();
|
||||
if (!result.isInitialized()) {
|
||||
throw newUninitializedMessageException(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model buildPartial() {
|
||||
com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model result = new com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model(this);
|
||||
int from_bitField0_ = bitField0_;
|
||||
int to_bitField0_ = 0;
|
||||
result.key_ = key_;
|
||||
result.timestamp_ = timestamp_;
|
||||
result.data_ = internalGetData();
|
||||
result.data_.makeImmutable();
|
||||
result.bitField0_ = to_bitField0_;
|
||||
onBuilt();
|
||||
return result;
|
||||
}
|
||||
|
||||
public Builder clone() {
|
||||
return (Builder) super.clone();
|
||||
}
|
||||
public Builder setField(
|
||||
com.google.protobuf.Descriptors.FieldDescriptor field,
|
||||
Object value) {
|
||||
return (Builder) super.setField(field, value);
|
||||
}
|
||||
public Builder clearField(
|
||||
com.google.protobuf.Descriptors.FieldDescriptor field) {
|
||||
return (Builder) super.clearField(field);
|
||||
}
|
||||
public Builder clearOneof(
|
||||
com.google.protobuf.Descriptors.OneofDescriptor oneof) {
|
||||
return (Builder) super.clearOneof(oneof);
|
||||
}
|
||||
public Builder setRepeatedField(
|
||||
com.google.protobuf.Descriptors.FieldDescriptor field,
|
||||
int index, Object value) {
|
||||
return (Builder) super.setRepeatedField(field, index, value);
|
||||
}
|
||||
public Builder addRepeatedField(
|
||||
com.google.protobuf.Descriptors.FieldDescriptor field,
|
||||
Object value) {
|
||||
return (Builder) super.addRepeatedField(field, value);
|
||||
}
|
||||
public Builder mergeFrom(com.google.protobuf.Message other) {
|
||||
if (other instanceof com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model) {
|
||||
return mergeFrom((com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model)other);
|
||||
} else {
|
||||
super.mergeFrom(other);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public Builder mergeFrom(com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model other) {
|
||||
if (other == com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model.getDefaultInstance()) return this;
|
||||
if (!other.getKey().isEmpty()) {
|
||||
key_ = other.key_;
|
||||
onChanged();
|
||||
}
|
||||
if (other.getTimestamp() != 0L) {
|
||||
setTimestamp(other.getTimestamp());
|
||||
}
|
||||
internalGetMutableData().mergeFrom(
|
||||
other.internalGetData());
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
|
||||
public final boolean isInitialized() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public Builder mergeFrom(
|
||||
com.google.protobuf.CodedInputStream input,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws java.io.IOException {
|
||||
com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model parsedMessage = null;
|
||||
try {
|
||||
parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
|
||||
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
|
||||
parsedMessage = (com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model) e.getUnfinishedMessage();
|
||||
throw e.unwrapIOException();
|
||||
} finally {
|
||||
if (parsedMessage != null) {
|
||||
mergeFrom(parsedMessage);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
private int bitField0_;
|
||||
|
||||
private java.lang.Object key_ = "";
|
||||
/**
|
||||
* <code>string key = 1;</code>
|
||||
*/
|
||||
public java.lang.String getKey() {
|
||||
java.lang.Object ref = key_;
|
||||
if (!(ref instanceof java.lang.String)) {
|
||||
com.google.protobuf.ByteString bs =
|
||||
(com.google.protobuf.ByteString) ref;
|
||||
java.lang.String s = bs.toStringUtf8();
|
||||
key_ = s;
|
||||
return s;
|
||||
} else {
|
||||
return (java.lang.String) ref;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* <code>string key = 1;</code>
|
||||
*/
|
||||
public com.google.protobuf.ByteString
|
||||
getKeyBytes() {
|
||||
java.lang.Object ref = key_;
|
||||
if (ref instanceof String) {
|
||||
com.google.protobuf.ByteString b =
|
||||
com.google.protobuf.ByteString.copyFromUtf8(
|
||||
(java.lang.String) ref);
|
||||
key_ = b;
|
||||
return b;
|
||||
} else {
|
||||
return (com.google.protobuf.ByteString) ref;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* <code>string key = 1;</code>
|
||||
*/
|
||||
public Builder setKey(
|
||||
java.lang.String value) {
|
||||
if (value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
key_ = value;
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>string key = 1;</code>
|
||||
*/
|
||||
public Builder clearKey() {
|
||||
|
||||
key_ = getDefaultInstance().getKey();
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>string key = 1;</code>
|
||||
*/
|
||||
public Builder setKeyBytes(
|
||||
com.google.protobuf.ByteString value) {
|
||||
if (value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
checkByteStringIsUtf8(value);
|
||||
|
||||
key_ = value;
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
|
||||
private long timestamp_ ;
|
||||
/**
|
||||
* <code>int64 timestamp = 2;</code>
|
||||
*/
|
||||
public long getTimestamp() {
|
||||
return timestamp_;
|
||||
}
|
||||
/**
|
||||
* <code>int64 timestamp = 2;</code>
|
||||
*/
|
||||
public Builder setTimestamp(long value) {
|
||||
|
||||
timestamp_ = value;
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>int64 timestamp = 2;</code>
|
||||
*/
|
||||
public Builder clearTimestamp() {
|
||||
|
||||
timestamp_ = 0L;
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
|
||||
private com.google.protobuf.MapField<
|
||||
java.lang.String, java.lang.String> data_;
|
||||
private com.google.protobuf.MapField<java.lang.String, java.lang.String>
|
||||
internalGetData() {
|
||||
if (data_ == null) {
|
||||
return com.google.protobuf.MapField.emptyMapField(
|
||||
DataDefaultEntryHolder.defaultEntry);
|
||||
}
|
||||
return data_;
|
||||
}
|
||||
private com.google.protobuf.MapField<java.lang.String, java.lang.String>
|
||||
internalGetMutableData() {
|
||||
onChanged();;
|
||||
if (data_ == null) {
|
||||
data_ = com.google.protobuf.MapField.newMapField(
|
||||
DataDefaultEntryHolder.defaultEntry);
|
||||
}
|
||||
if (!data_.isMutable()) {
|
||||
data_ = data_.copy();
|
||||
}
|
||||
return data_;
|
||||
}
|
||||
|
||||
public int getDataCount() {
|
||||
return internalGetData().getMap().size();
|
||||
}
|
||||
/**
|
||||
* <code>map<string, string> data = 3;</code>
|
||||
*/
|
||||
|
||||
public boolean containsData(
|
||||
java.lang.String key) {
|
||||
if (key == null) { throw new java.lang.NullPointerException(); }
|
||||
return internalGetData().getMap().containsKey(key);
|
||||
}
|
||||
/**
|
||||
* Use {@link #getDataMap()} instead.
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
public java.util.Map<java.lang.String, java.lang.String> getData() {
|
||||
return getDataMap();
|
||||
}
|
||||
/**
|
||||
* <code>map<string, string> data = 3;</code>
|
||||
*/
|
||||
|
||||
public java.util.Map<java.lang.String, java.lang.String> getDataMap() {
|
||||
return internalGetData().getMap();
|
||||
}
|
||||
/**
|
||||
* <code>map<string, string> data = 3;</code>
|
||||
*/
|
||||
|
||||
public java.lang.String getDataOrDefault(
|
||||
java.lang.String key,
|
||||
java.lang.String defaultValue) {
|
||||
if (key == null) { throw new java.lang.NullPointerException(); }
|
||||
java.util.Map<java.lang.String, java.lang.String> map =
|
||||
internalGetData().getMap();
|
||||
return map.containsKey(key) ? map.get(key) : defaultValue;
|
||||
}
|
||||
/**
|
||||
* <code>map<string, string> data = 3;</code>
|
||||
*/
|
||||
|
||||
public java.lang.String getDataOrThrow(
|
||||
java.lang.String key) {
|
||||
if (key == null) { throw new java.lang.NullPointerException(); }
|
||||
java.util.Map<java.lang.String, java.lang.String> map =
|
||||
internalGetData().getMap();
|
||||
if (!map.containsKey(key)) {
|
||||
throw new java.lang.IllegalArgumentException();
|
||||
}
|
||||
return map.get(key);
|
||||
}
|
||||
|
||||
public Builder clearData() {
|
||||
internalGetMutableData().getMutableMap()
|
||||
.clear();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>map<string, string> data = 3;</code>
|
||||
*/
|
||||
|
||||
public Builder removeData(
|
||||
java.lang.String key) {
|
||||
if (key == null) { throw new java.lang.NullPointerException(); }
|
||||
internalGetMutableData().getMutableMap()
|
||||
.remove(key);
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Use alternate mutation accessors instead.
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
public java.util.Map<java.lang.String, java.lang.String>
|
||||
getMutableData() {
|
||||
return internalGetMutableData().getMutableMap();
|
||||
}
|
||||
/**
|
||||
* <code>map<string, string> data = 3;</code>
|
||||
*/
|
||||
public Builder putData(
|
||||
java.lang.String key,
|
||||
java.lang.String value) {
|
||||
if (key == null) { throw new java.lang.NullPointerException(); }
|
||||
if (value == null) { throw new java.lang.NullPointerException(); }
|
||||
internalGetMutableData().getMutableMap()
|
||||
.put(key, value);
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>map<string, string> data = 3;</code>
|
||||
*/
|
||||
|
||||
public Builder putAllData(
|
||||
java.util.Map<java.lang.String, java.lang.String> values) {
|
||||
internalGetMutableData().getMutableMap()
|
||||
.putAll(values);
|
||||
return this;
|
||||
}
|
||||
public final Builder setUnknownFields(
|
||||
final com.google.protobuf.UnknownFieldSet unknownFields) {
|
||||
return this;
|
||||
}
|
||||
|
||||
public final Builder mergeUnknownFields(
|
||||
final com.google.protobuf.UnknownFieldSet unknownFields) {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
// @@protoc_insertion_point(builder_scope:com.farsunset.cim.sdk.android.model.proto.Model)
|
||||
}
|
||||
|
||||
// @@protoc_insertion_point(class_scope:com.farsunset.cim.sdk.android.model.proto.Model)
|
||||
private static final com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model DEFAULT_INSTANCE;
|
||||
static {
|
||||
DEFAULT_INSTANCE = new com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model();
|
||||
}
|
||||
|
||||
public static com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model getDefaultInstance() {
|
||||
return DEFAULT_INSTANCE;
|
||||
}
|
||||
|
||||
private static final com.google.protobuf.Parser<Model>
|
||||
PARSER = new com.google.protobuf.AbstractParser<Model>() {
|
||||
public Model parsePartialFrom(
|
||||
com.google.protobuf.CodedInputStream input,
|
||||
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
|
||||
throws com.google.protobuf.InvalidProtocolBufferException {
|
||||
return new Model(input, extensionRegistry);
|
||||
}
|
||||
};
|
||||
|
||||
public static com.google.protobuf.Parser<Model> parser() {
|
||||
return PARSER;
|
||||
}
|
||||
|
||||
@java.lang.Override
|
||||
public com.google.protobuf.Parser<Model> getParserForType() {
|
||||
return PARSER;
|
||||
}
|
||||
|
||||
public com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model getDefaultInstanceForType() {
|
||||
return DEFAULT_INSTANCE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final com.google.protobuf.Descriptors.Descriptor
|
||||
internal_static_com_farsunset_cim_sdk_android_model_proto_Model_descriptor;
|
||||
private static final
|
||||
com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
|
||||
internal_static_com_farsunset_cim_sdk_android_model_proto_Model_fieldAccessorTable;
|
||||
private static final com.google.protobuf.Descriptors.Descriptor
|
||||
internal_static_com_farsunset_cim_sdk_android_model_proto_Model_DataEntry_descriptor;
|
||||
private static final
|
||||
com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
|
||||
internal_static_com_farsunset_cim_sdk_android_model_proto_Model_DataEntry_fieldAccessorTable;
|
||||
|
||||
public static com.google.protobuf.Descriptors.FileDescriptor
|
||||
getDescriptor() {
|
||||
return descriptor;
|
||||
}
|
||||
private static com.google.protobuf.Descriptors.FileDescriptor
|
||||
descriptor;
|
||||
static {
|
||||
java.lang.String[] descriptorData = {
|
||||
"\n\016SentBody.proto\022)com.farsunset.cim.sdk." +
|
||||
"android.model.proto\"\236\001\n\005Model\022\013\n\003key\030\001 \001" +
|
||||
"(\t\022\021\n\ttimestamp\030\002 \001(\003\022H\n\004data\030\003 \003(\0132:.co" +
|
||||
"m.farsunset.cim.sdk.android.model.proto." +
|
||||
"Model.DataEntry\032+\n\tDataEntry\022\013\n\003key\030\001 \001(" +
|
||||
"\t\022\r\n\005value\030\002 \001(\t:\0028\001B\017B\rSentBodyProtob\006p" +
|
||||
"roto3"
|
||||
};
|
||||
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
|
||||
new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() {
|
||||
public com.google.protobuf.ExtensionRegistry assignDescriptors(
|
||||
com.google.protobuf.Descriptors.FileDescriptor root) {
|
||||
descriptor = root;
|
||||
return null;
|
||||
}
|
||||
};
|
||||
com.google.protobuf.Descriptors.FileDescriptor
|
||||
.internalBuildGeneratedFileFrom(descriptorData,
|
||||
new com.google.protobuf.Descriptors.FileDescriptor[] {
|
||||
}, assigner);
|
||||
internal_static_com_farsunset_cim_sdk_android_model_proto_Model_descriptor =
|
||||
getDescriptor().getMessageTypes().get(0);
|
||||
internal_static_com_farsunset_cim_sdk_android_model_proto_Model_fieldAccessorTable = new
|
||||
com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
|
||||
internal_static_com_farsunset_cim_sdk_android_model_proto_Model_descriptor,
|
||||
new java.lang.String[] { "Key", "Timestamp", "Data", });
|
||||
internal_static_com_farsunset_cim_sdk_android_model_proto_Model_DataEntry_descriptor =
|
||||
internal_static_com_farsunset_cim_sdk_android_model_proto_Model_descriptor.getNestedTypes().get(0);
|
||||
internal_static_com_farsunset_cim_sdk_android_model_proto_Model_DataEntry_fieldAccessorTable = new
|
||||
com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
|
||||
internal_static_com_farsunset_cim_sdk_android_model_proto_Model_DataEntry_descriptor,
|
||||
new java.lang.String[] { "Key", "Value", });
|
||||
}
|
||||
|
||||
// @@protoc_insertion_point(outer_class_scope)
|
||||
}
|
9
cim_for_mina/cim-client-android/.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/workspace.xml
|
||||
/.idea/libraries
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
105
cim_for_mina/cim-client-android/.idea/misc.xml
generated
Normal file
@ -0,0 +1,105 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="EntryPointsManager">
|
||||
<entry_points version="2.0" />
|
||||
</component>
|
||||
<component name="NullableNotNullManager">
|
||||
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
|
||||
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
|
||||
<option name="myNullables">
|
||||
<value>
|
||||
<list size="4">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
|
||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
|
||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
<option name="myNotNulls">
|
||||
<value>
|
||||
<list size="4">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
|
||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
|
||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectInspectionProfilesVisibleTreeState">
|
||||
<entry key="Project Default">
|
||||
<profile-state>
|
||||
<expanded-state>
|
||||
<State>
|
||||
<id />
|
||||
</State>
|
||||
<State>
|
||||
<id>Android</id>
|
||||
</State>
|
||||
<State>
|
||||
<id>Android > Lint > Correctness</id>
|
||||
</State>
|
||||
<State>
|
||||
<id>Android > Lint > Internationalization</id>
|
||||
</State>
|
||||
<State>
|
||||
<id>Android > Lint > Security</id>
|
||||
</State>
|
||||
<State>
|
||||
<id>CorrectnessLintAndroid</id>
|
||||
</State>
|
||||
<State>
|
||||
<id>Gradle</id>
|
||||
</State>
|
||||
<State>
|
||||
<id>LintAndroid</id>
|
||||
</State>
|
||||
<State>
|
||||
<id>Probable bugsGradle</id>
|
||||
</State>
|
||||
</expanded-state>
|
||||
<selected-state>
|
||||
<State>
|
||||
<id>Android</id>
|
||||
</State>
|
||||
</selected-state>
|
||||
</profile-state>
|
||||
</entry>
|
||||
</component>
|
||||
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
|
||||
<OptionsSetting value="true" id="Add" />
|
||||
<OptionsSetting value="true" id="Remove" />
|
||||
<OptionsSetting value="true" id="Checkout" />
|
||||
<OptionsSetting value="true" id="Update" />
|
||||
<OptionsSetting value="true" id="Status" />
|
||||
<OptionsSetting value="true" id="Edit" />
|
||||
<ConfirmationsSetting value="0" id="Add" />
|
||||
<ConfirmationsSetting value="0" id="Remove" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
<option name="id" value="Android" />
|
||||
</component>
|
||||
<component name="SuppressionsComponent">
|
||||
<option name="suppComments" value="[]" />
|
||||
</component>
|
||||
<component name="masterDetails">
|
||||
<states>
|
||||
<state key="ProjectJDKs.UI">
|
||||
<settings>
|
||||
<last-edited>1.8</last-edited>
|
||||
<splitter-proportions>
|
||||
<option name="proportions">
|
||||
<list>
|
||||
<option value="0.2" />
|
||||
</list>
|
||||
</option>
|
||||
</splitter-proportions>
|
||||
</settings>
|
||||
</state>
|
||||
</states>
|
||||
</component>
|
||||
</project>
|
1
cim_for_mina/cim-client-android/app/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/build
|
35
cim_for_mina/cim-client-android/app/build.gradle
Normal file
@ -0,0 +1,35 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 25
|
||||
buildToolsVersion "25.0.2"
|
||||
defaultConfig {
|
||||
applicationId "com.farsunset.ichat.example"
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 21
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
lintOptions {
|
||||
checkReleaseBuilds false
|
||||
abortOnError false
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
compile 'com.android.support:appcompat-v7:25.1.0'
|
||||
compile 'com.google.protobuf:protobuf-java:3.2.0'
|
||||
compile 'org.apache.mina:mina-core:2.0.16'
|
||||
compile 'org.slf4j:slf4j-api:1.7.24'
|
||||
compile 'org.slf4j:slf4j-nop:1.7.24'
|
||||
}
|
BIN
cim_for_mina/cim-client-android/app/libs/cim-server-sdk-3.0.jar
Normal file
17
cim_for_mina/cim-client-android/app/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in D:\Program Files (x86)\dev\android-sdk-windos/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.farsunset.ichat.example"
|
||||
android:versionCode="3"
|
||||
android:versionName="2.1.0" >
|
||||
android:versionCode="30"
|
||||
android:versionName="3.0.0" >
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
@ -10,10 +10,6 @@
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
<uses-permission android:name="android.permission.GET_TASKS" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
||||
<uses-sdk
|
||||
android:minSdkVersion="10"
|
||||
android:targetSdkVersion="19" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
@ -55,7 +51,7 @@
|
||||
<service android:name="com.farsunset.cim.sdk.android.CIMPushService" android:process=":cimpush" />
|
||||
|
||||
<!--消息接受广播注册-->
|
||||
<receiver android:name="com.farsunset.ichat.example.receiver.CustomCIMMessageReceiver" android:exported="false">
|
||||
<receiver android:name="com.farsunset.ichat.example.receiver.CIMPushManagerReceiver" android:exported="false">
|
||||
<intent-filter android:priority="0x7fffffff">
|
||||
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/> <!-- 网络变化广播 -->
|
||||
<action android:name="com.farsunset.cim.MESSAGE_RECEIVED"/><!-- 消息广播action -->
|
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.ichat.example.adapter;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
import com.farsunset.cim.sdk.android.model.Message;
|
||||
|
||||
public class MessageTimeDescComparator implements Comparator<Message>{
|
||||
|
||||
@Override
|
||||
public int compare(Message arg0, Message arg1) {
|
||||
|
||||
return (int) (arg1.getTimestamp() - arg0.getTimestamp()) ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -1,9 +1,24 @@
|
||||
/**
|
||||
* probject:cim
|
||||
* @version 2.0
|
||||
*
|
||||
* @author 3979434@qq.com
|
||||
*/
|
||||
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.ichat.example.adapter;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
@ -67,7 +82,7 @@ public class SystemMsgListViewAdapter extends BaseAdapter {
|
||||
((TextView) chatItemView.findViewById(R.id.time)).setText(getDateTimeString(Long.valueOf(msg.getTimestamp())));
|
||||
|
||||
((TextView) chatItemView.findViewById(R.id.content)).setText(msg.getContent() );
|
||||
((ImageView) chatItemView.findViewById(R.id.headImageView)).setImageResource(R.drawable.icon_recent_sysmsg);
|
||||
((ImageView) chatItemView.findViewById(R.id.headImageView)).setImageResource(R.drawable.icon);
|
||||
|
||||
return chatItemView;
|
||||
}
|
@ -0,0 +1,118 @@
|
||||
/**
|
||||
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.ichat.example.app;
|
||||
|
||||
|
||||
import com.farsunset.cim.sdk.android.CIMEventListener;
|
||||
import com.farsunset.cim.sdk.android.CIMListenerManager;
|
||||
import com.farsunset.cim.sdk.android.model.Message;
|
||||
import com.farsunset.cim.sdk.android.model.ReplyBody;
|
||||
import com.farsunset.cim.sdk.android.model.SentBody;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.net.NetworkInfo;
|
||||
import android.os.Bundle;
|
||||
|
||||
public abstract class CIMMonitorActivity extends Activity implements CIMEventListener{
|
||||
|
||||
|
||||
CommonBaseControl commonBaseControl;
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
CIMListenerManager.registerMessageListener(this);
|
||||
|
||||
commonBaseControl = new CommonBaseControl(this);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
super.finish();
|
||||
CIMListenerManager.removeMessageListener(this);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRestart() {
|
||||
super.onRestart();
|
||||
CIMListenerManager.registerMessageListener(this);
|
||||
}
|
||||
|
||||
|
||||
public void showProgressDialog(String title,String content)
|
||||
{
|
||||
commonBaseControl.showProgressDialog(title, content);
|
||||
}
|
||||
|
||||
public void hideProgressDialog()
|
||||
{
|
||||
commonBaseControl.hideProgressDialog();
|
||||
}
|
||||
|
||||
public void showToask(String hint){
|
||||
|
||||
commonBaseControl.showToask(hint);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void onMessageReceived(Message arg0){};
|
||||
|
||||
@Override
|
||||
public void onNetworkChanged(NetworkInfo info){}
|
||||
|
||||
/**
|
||||
* 与服务端断开连接时回调,不要在里面做连接服务端的操作
|
||||
*/
|
||||
@Override
|
||||
public void onConnectionClosed() {}
|
||||
|
||||
@Override
|
||||
public void onConnectionFailed() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEventDispatchOrder() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接服务端成功时回调
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void onConnectionSuccessed(boolean arg0) {}
|
||||
|
||||
|
||||
@Override
|
||||
public void onReplyReceived(ReplyBody arg0) {}
|
||||
|
||||
@Override
|
||||
public void onSentSuccessed(SentBody sentBody) {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
/**
|
||||
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.ichat.example.app;
|
||||
|
||||
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.widget.Toast;
|
||||
|
||||
|
||||
public class CommonBaseControl {
|
||||
|
||||
private ProgressDialog progressDialog;
|
||||
|
||||
Context mMontent;
|
||||
|
||||
|
||||
public CommonBaseControl(Context content)
|
||||
{
|
||||
this.mMontent = content;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void showProgressDialog(String title,String message)
|
||||
{
|
||||
if(progressDialog==null)
|
||||
{
|
||||
|
||||
progressDialog = ProgressDialog.show(mMontent, title, message, true, true);
|
||||
}else if(progressDialog.isShowing())
|
||||
{
|
||||
progressDialog.setTitle(title);
|
||||
progressDialog.setMessage(message);
|
||||
}
|
||||
|
||||
progressDialog.show();
|
||||
|
||||
}
|
||||
|
||||
public void hideProgressDialog()
|
||||
{
|
||||
|
||||
if(progressDialog!=null&&progressDialog.isShowing())
|
||||
{
|
||||
progressDialog.dismiss();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void showToask(String hint){
|
||||
|
||||
Toast toast=Toast.makeText(mMontent,hint,Toast.LENGTH_SHORT);
|
||||
toast.show();
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.ichat.example.app;
|
||||
|
||||
public interface Constant {
|
||||
|
||||
//服务端IP地址
|
||||
public static final String CIM_SERVER_HOST = "172.168.11.28";
|
||||
|
||||
|
||||
//注意,这里的端口不是tomcat的端口,CIM端口在服务端spring-cim.xml中配置的,没改动就使用默认的23456
|
||||
public static final int CIM_SERVER_PORT = 23456;
|
||||
|
||||
public static interface MessageType{
|
||||
|
||||
|
||||
//用户之间的普通消息
|
||||
public static final String TYPE_0 = "0";
|
||||
|
||||
|
||||
//下线类型
|
||||
String TYPE_999 = "999";
|
||||
}
|
||||
|
||||
|
||||
public static interface MessageStatus{
|
||||
|
||||
//消息未读
|
||||
public static final String STATUS_0 = "0";
|
||||
//消息已经读取
|
||||
public static final String STATUS_1 = "1";
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,126 @@
|
||||
/**
|
||||
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.ichat.example.receiver;
|
||||
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.NetworkInfo;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
|
||||
import com.farsunset.cim.sdk.android.CIMEventBroadcastReceiver;
|
||||
import com.farsunset.cim.sdk.android.CIMListenerManager;
|
||||
import com.farsunset.cim.sdk.android.model.Message;
|
||||
import com.farsunset.cim.sdk.android.model.ReplyBody;
|
||||
import com.farsunset.ichat.example.R;
|
||||
import com.farsunset.ichat.example.ui.SystemMessageActivity;
|
||||
|
||||
import static android.R.id.message;
|
||||
import static com.farsunset.ichat.example.R.id.content;
|
||||
|
||||
/**
|
||||
* 消息入口,所有消息都会经过这里
|
||||
* @author 3979434
|
||||
*
|
||||
*/
|
||||
public final class CIMPushManagerReceiver extends CIMEventBroadcastReceiver {
|
||||
|
||||
private NotificationManager notificationManager;
|
||||
|
||||
//当收到消息时,会执行onMessageReceived,这里是消息第一入口
|
||||
|
||||
@Override
|
||||
public void onMessageReceived(Message message, Intent intent) {
|
||||
|
||||
//调用分发消息监听
|
||||
CIMListenerManager.notifyOnMessageReceived(message);
|
||||
|
||||
//以开头的为动作消息,无须显示,如被强行下线消息Constant.TYPE_999
|
||||
if(message.getAction().startsWith("9"))
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
showNotify(context,message);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void showNotify(Context context , Message msg)
|
||||
{
|
||||
|
||||
this.notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
String title = "系统消息";
|
||||
|
||||
PendingIntent contentIntent = PendingIntent.getActivity(context,1, new Intent(context,SystemMessageActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
final NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
|
||||
builder.setAutoCancel(true);
|
||||
builder.setDefaults(Notification.DEFAULT_ALL);
|
||||
builder.setWhen(msg.getTimestamp());
|
||||
builder.setSmallIcon(R.drawable.icon);
|
||||
builder.setTicker(title);
|
||||
builder.setContentTitle(title);
|
||||
builder.setContentText(msg.getContent());
|
||||
builder.setDefaults(Notification.DEFAULT_LIGHTS);
|
||||
builder.setContentIntent(contentIntent);
|
||||
final Notification notification = builder.build();
|
||||
|
||||
|
||||
notificationManager.notify(R.drawable.icon, notification);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onNetworkChanged(NetworkInfo info) {
|
||||
CIMListenerManager.notifyOnNetworkChanged(info);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onConnectionSuccessed(boolean hasAutoBind) {
|
||||
CIMListenerManager.notifyOnConnectionSuccessed(hasAutoBind);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectionClosed() {
|
||||
CIMListenerManager.notifyOnConnectionClosed();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onReplyReceived(ReplyBody body) {
|
||||
CIMListenerManager.notifyOnReplyReceived(body);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void onConnectionFailed() {
|
||||
// TODO Auto-generated method stub
|
||||
CIMListenerManager.notifyOnConnectionFailed();
|
||||
}
|
||||
|
||||
}
|
@ -1,9 +1,24 @@
|
||||
/**
|
||||
* probject:cim
|
||||
* @version 2.0
|
||||
*
|
||||
* @author 3979434@qq.com
|
||||
*/
|
||||
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.ichat.example.ui;
|
||||
|
||||
import android.content.Intent;
|
||||
@ -44,18 +59,13 @@ public class LoginActivity extends CIMMonitorActivity implements
|
||||
|
||||
if (!"".equals(accountEdit.getText().toString().trim())) {
|
||||
showProgressDialog("提示", "正在登陆,请稍后......");
|
||||
if(CIMPushManager.getState(this) == CIMPushManager.STATE_NORMAL )
|
||||
{
|
||||
if (CIMPushManager.isConnected(this)) {
|
||||
CIMPushManager.bindAccount(this, accountEdit.getText().toString().trim());
|
||||
return;
|
||||
} else {
|
||||
CIMPushManager.connect(this, Constant.CIM_SERVER_HOST, Constant.CIM_SERVER_PORT);
|
||||
}
|
||||
if(CIMPushManager.getState(this) == CIMPushManager.STATE_STOPED )
|
||||
{
|
||||
CIMPushManager.connect(this,Constant.CIM_SERVER_HOST, Constant.CIM_SERVER_PORT);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
@ -1,9 +1,24 @@
|
||||
/**
|
||||
* probject:cim
|
||||
* @version 2.0
|
||||
*
|
||||
* @author 3979434@qq.com
|
||||
*/
|
||||
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.ichat.example.ui;
|
||||
|
||||
|
@ -1,9 +1,24 @@
|
||||
/**
|
||||
* probject:cim
|
||||
* @version 2.0
|
||||
*
|
||||
* @author 3979434@qq.com
|
||||
*/
|
||||
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
***************************************************************************************
|
||||
* *
|
||||
* Website : http://www.farsunset.com *
|
||||
* *
|
||||
***************************************************************************************
|
||||
*/
|
||||
package com.farsunset.ichat.example.ui;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -25,29 +40,19 @@ import com.farsunset.ichat.example.R;
|
||||
import com.farsunset.ichat.example.adapter.SystemMsgListViewAdapter;
|
||||
import com.farsunset.ichat.example.app.CIMMonitorActivity;
|
||||
import com.farsunset.ichat.example.app.Constant;
|
||||
import com.farsunset.ichat.example.network.HttpAPIRequester;
|
||||
import com.farsunset.ichat.example.network.HttpAPIResponser;
|
||||
|
||||
public class SystemMessageActivity extends CIMMonitorActivity implements OnClickListener, HttpAPIResponser{
|
||||
public class SystemMessageActivity extends CIMMonitorActivity implements OnClickListener{
|
||||
|
||||
protected ListView chatListView;
|
||||
int currentPage = 1;
|
||||
protected SystemMsgListViewAdapter adapter;
|
||||
private ArrayList<Message> list;
|
||||
|
||||
public HashMap<String, Object> apiParams = new HashMap<String, Object>();
|
||||
|
||||
//客户端向客户端发送消息接口地址
|
||||
public final static String SEND_MESSAGE_API_URL=Constant.SERVER_URL+"/cgi/message_send.api";
|
||||
|
||||
HttpAPIRequester requester ;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_system_chat);
|
||||
initViews();
|
||||
requester = new HttpAPIRequester(this);
|
||||
|
||||
|
||||
//绑定账号成功,获取离线消息
|
||||
getOfflineMessage();
|
||||
}
|
||||
@ -73,7 +78,7 @@ public class SystemMessageActivity extends CIMMonitorActivity implements OnClick
|
||||
@Override
|
||||
public void onMessageReceived(Message message) {
|
||||
|
||||
if(message.getType().equals(Constant.MessageType.TYPE_999))
|
||||
if(message.getAction().equals(Constant.MessageType.TYPE_999))
|
||||
{
|
||||
//返回登录页面,停止接受消息
|
||||
CIMPushManager.stop(this);
|
||||
@ -93,11 +98,11 @@ public class SystemMessageActivity extends CIMMonitorActivity implements OnClick
|
||||
|
||||
}
|
||||
|
||||
//获取离线消息,代码示例,前提是服务端要实现此功能
|
||||
//获取离线消息,代码示例,前提是服务端要实现此功能,建议使用http 接口拉去大量的离线消息
|
||||
private void getOfflineMessage()
|
||||
{
|
||||
SentBody sent = new SentBody();
|
||||
sent.setKey(CIMConstant.RequestKey.CLIENT_OFFLINE_MESSAGE);
|
||||
sent.setKey(CIMConstant.RequestKey.CLIENT_PULL_MESSAGE);
|
||||
sent.put("account", this.getIntent().getStringExtra("account"));
|
||||
CIMPushManager.sendRequest(this, sent);
|
||||
}
|
||||
@ -115,38 +120,8 @@ public class SystemMessageActivity extends CIMMonitorActivity implements OnClick
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//发送消息示范,用户客户端与客户端之间的消息发送
|
||||
private void sendMessage() throws Exception
|
||||
{
|
||||
|
||||
requester.execute(SEND_MESSAGE_API_URL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(String data,String url) {
|
||||
hideProgressDialog();
|
||||
|
||||
showToask("发送成功");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getRequestParams() {
|
||||
|
||||
apiParams.put("content", "hello world!");
|
||||
apiParams.put("sender", "xiaogou");//发送者账号
|
||||
apiParams.put("receiver", "xiaomao");//消息接收者账号
|
||||
apiParams.put("type",Constant.MessageType.TYPE_0);
|
||||
|
||||
return apiParams;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequest() {
|
||||
showProgressDialog("提示", "正在发送消息...");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
@ -158,9 +133,6 @@ public class SystemMessageActivity extends CIMMonitorActivity implements OnClick
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailed(Exception e,String url) {}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
|
||||
@ -173,4 +145,4 @@ public class SystemMessageActivity extends CIMMonitorActivity implements OnClick
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 414 B After Width: | Height: | Size: 414 B |
Before Width: | Height: | Size: 883 B After Width: | Height: | Size: 883 B |
Before Width: | Height: | Size: 878 B After Width: | Height: | Size: 878 B |
Before Width: | Height: | Size: 479 B After Width: | Height: | Size: 479 B |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 232 B After Width: | Height: | Size: 232 B |
Before Width: | Height: | Size: 530 B After Width: | Height: | Size: 530 B |
Before Width: | Height: | Size: 238 B After Width: | Height: | Size: 238 B |
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
@ -17,7 +17,6 @@
|
||||
android:layout_height="91.0dip"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="68.0dip"
|
||||
android:background="@drawable/card_avatar"
|
||||
android:scaleType="fitXY"
|
||||
android:src="@drawable/login_default_avatar" />
|
||||
|